在我的应用程序中,我定义了以下类:
@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());
}
如果我尝试向论坛实体添加新帖子,lastActivity
字段会在@PrePersist
回调中在数据库中正确更新。
但是,如果我尝试使用以下代码更新post实体:
entityManager.getTransaction().begin();
Post post = entityManager.find(Post.class, "postId");
post.setContent("New post text");
entityManager.merge(post);
entityManager.getTransaction().commit();
仅更新帖子数据且lastActivity
字段值不会更改。在我看来,@PreUpdate
方法应该做的伎俩和更新论坛实体。
这是一个错误还是我错过了什么?
答案 0 :(得分:8)
这不是错误,即使通过快速尝试,这对我有用。负面消息是,由于以下原因,它无法保证有效:
从JPA 2.0规范中的第93页开始:
通常,便携式应用程序的生命周期方法不应该 调用EntityManager或Query操作,访问其他实体 实例,或修改同一持久性内的关系 上下文。[43]生命周期回调方法可以修改 调用它的实体的非关系状态。
并且第95页:
关于回调方法是否依赖于实现 在生命周期事件级联之前或之后调用 相关实体。应用程序不应该依赖于此顺序。
答案 1 :(得分:0)
post.merge()
在这里没用。 post
已明确附于会议。
确保已将content
属性映射到列,如果不是,则Hibernate无法判断实体是否为脏,因此将更改刷新到DB。