我遇到了一个奇怪的问题:我有一个实体和该类的听众,
@Entity
@EntityListeners(Listener.class)
public class Foo {
@Id long id;
@ElementCollection Map<String, String> map;
// getters and setters
}
public class Listener {
@PreUpdate
@PrePersist
public void preUpdate(Foo foo) {
System.out.println(foo);
System.out.println(foo.getMap().size());
}
}
@Stateless
public class TestDAO {
@PersistenceContext
EntityManager em;
public void testMerge(Foo foo) {
foo.getMap().put("foo", "test");
System.out.println(foo);
System.out.println(foo.getMap().size());
this.em.merge(foo);
}
}
然后当我执行testMerge
时,我得到了这个输出(使用SQL调试更新):
Foo@15bcfa3c
1
Foo@671144f9
0
Hibernate: insert into Foo values ( )
Hibernate: insert into Foo_map (Foo_id, map_KEY, map) values (?, ?, ?) // 1, 'foo', 'test'
因此地图会在数据库中正确保存,但传递给侦听器的实体会有一个空地图。发生了什么事?
更新:Jira问题和测试用例 相关的Jira问题:https://hibernate.atlassian.net/browse/HHH-11414 测试用例:https://github.com/heruan/hibernate-testcase/tree/HHH-11414
答案 0 :(得分:0)
这是一个棘手的问题,但是如果你调试testMerge代码和监听器方法,你可能会发现Foo的实际实例是不同的。 现在是@PreUpdate / @PostUpdate调用的情况。
对于@PrePersist / @PostPersist,情况并非如此,因为该方法始终接收相同的实体实例。
不确定您使用的是哪个版本的Hibernate,但我记得当时我正在为3.x版本做一个项目。
<强>更新强>
只是提醒你,因为我正在使用Pre / Post Upate测试合并,我发现唯一的一次,merge()操作可以调用事件监听器是在新实体上调用它时尚未坚持。然后它作为一个persist()操作本身,并调用@PrePersist注释类。因此,您可能永远无法通过该配置实现您所寻求的目标。