Reputation: 46
We are using Hibernate 5.2.17 in our project and populate the last modification date within a @PreUpdate
entity callback.
After a lengthy debugging session it seems like that when
the changes done to the entity within the callback are not persisted on database level.
I was about to file this as bug for Hibernate, but before that get feedback on whether we do something wrong.
Entity
@Entity(name = "Person")
private static class Person {
@Id
@GeneratedValue
private int id;
private String name;
private Instant createdAt;
private Instant lastUpdatedAt;
@ElementCollection(fetch = FetchType.LAZY)
private List<String> tags;
@Lob
@Basic(fetch = FetchType.LAZY)
private ByteBuffer image;
@PrePersist
void beforeCreate() {
createdAt = Instant.now();
}
@PreUpdate
void beforeUpdate() {
lastUpdatedAt = Instant.now();
}
}
Test (abbreviated)
@Test
public void testPreUpdateModificationDate() throws Exception {
EntityManager em = getOrCreateEntityManager();
em.getTransaction().begin();
Person p = new Person();
em.persist(p);
em.getTransaction().commit();
int personId = p.id;
em.refresh(p);
p = em.find(Person.class, personId);
assertNotNull(p);
assertNotNull(p.createdAt);
assertNull(p.lastUpdatedAt);
p.name = "New Name";
em.getTransaction().begin();
em.merge(p);
em.getTransaction().commit();
assertEquals(p.name, "New Name");
em.refresh(p);
p = em.find(Person.class, personId);
// the last line fails
assertNotNull(p.lastUpdatedAt);
}
As soon as the one of the lazily loaded attributes is removed from Person
, the test runs successfully.
In debugging it looks like the SQL generation for an entity update does not consider the fields changed in @PreUpdate
as dirty. The class org.hibernate.persister.entity.AbstractPersister
has a different SQL generation for "dynamic updates" which is chosen automatically when bytecode enhancement is active and more than 1 fetch group is present.
Upvotes: 1
Views: 986
Reputation: 46
The issue has been fixed in Hibernate in 5.3.3.
Bug report: https://hibernate.atlassian.net/browse/HHH-12718
Upvotes: 1
Reputation: 11551
Works for me: not sure what is the issue, but you have many strange things. Perhaps start with this simple example and expand to your code to find the difference:
tx.begin();
Person p = new Person();
em.persist(p);
tx.commit();
System.out.println(p);
tx.begin();
p.setName( "New Name" );
tx.commit();
System.out.println(p);
Upvotes: 0