In my application I defined following classes:
@Entity
@Table(name = "forums")
public class Forum {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
private String name;
private Date lastActivity;
@OneToMany(mappedBy = "forum", cascade = { CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE })
private List<Post> posts;
@Entity
@Table(name = "posts")
public class Post {
@Id
@GeneratedValue(generator = "system-uuid")
@GenericGenerator(name = "system-uuid", strategy = "uuid")
private String id;
private String username;
private String content;
private Date creationDate;
@ManyToOne(optional = false, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
private Forum forum;
public Post() {
creationDate = new Date();
}
@PrePersist
private void onPersist() {
System.out.println开发者_如何转开发(getClass().getName() + ": onPersist");
if (creationDate == null) {
creationDate = new Date();
}
forum.setLastActivity(creationDate);
}
@PreUpdate
private void onUpdate() {
forum.setLastActivity(new Date());
}
If I try adding new posts to forum entity, lastActivity
field is correctly updated in database by @PrePersist
callback.
But if I try to update post entity using following code:
entityManager.getTransaction().begin();
Post post = entityManager.find(Post.class, "postId");
post.setContent("New post text");
entityManager.merge(post);
entityManager.getTransaction().commit();
only post data are updated and lastActivity
field value doesn't change. In my opinion @PreUpdate
method should do the trick and update Forum entity.
Is this a bug or am I missing something?
It is not bug, even that with a fast try this worked for me way you expected. Negative news is that it is not guaranteed to work, because of:
From page 93 in JPA 2.0 specification:
In general, the lifecycle method of a portable application should not invoke EntityManager or Query operations, access other entity instances, or modify relationships within the same persistence context.[43] A lifecycle callback method may modify the non-relationship state of the entity on which it is invoked.
And page 95:
It is implementation-dependent as to whether callback methods are invoked before or after the cascading of the lifecycle events to related entities. Applications should not depend on this ordering.
post.merge()
has no use here. post
is clearly attached to the session already.
Make sure you've got the content
attribute mapped to a column, if it is not, Hibernate has no way of telling if the entity is dirty, and therefore flush the changes to the DB.
精彩评论