Hibernate@PreUpdate/@PrePersist不一致
我遇到了一个奇怪的问题:我有一个实体和该类的侦听器Hibernate@PreUpdate/@PrePersist不一致,hibernate,jpa,entitylisteners,Hibernate,Jpa,Entitylisteners,我遇到了一个奇怪的问题:我有一个实体和该类的侦听器 @Entity @EntityListeners(Listener.class) public class Foo { @Id long id; @ElementCollection Map<String, String> map; // getters and setters } public class Listener { @PreUpdate @PrePersist
@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);
}
}
因此映射被正确地保存在数据库中,但是传递给侦听器的实体有一个空映射。发生了什么事
更新:Jira问题和测试用例
相关Jira问题:
测试用例:这是一个棘手的问题,但是如果调试testMerge代码和侦听器方法,您可能会发现Foo的实际实例是不同的。 现在@PreUpdate/@postpdate调用就是这样 对于@PrePersist/@PostPersist,情况并非如此,因为该方法始终接收相同的实体实例 不确定您使用的是哪个版本的Hibernate,但我记得不久前我在为3.x版本做项目时注意到了这一点 更新
只是提醒您,当我在Upate之前/之后测试merge时,我发现merge()操作可以调用事件侦听器的唯一时间是在尚未持久化的新实体上调用它时。然后,它本身充当persist()操作,并调用@PrePersist注释类。因此,您可能永远无法通过该配置实现所需的功能。这是一个棘手的问题,但是如果您调试testMerge代码和侦听器方法,您可能会发现Foo的实际实例是不同的。 现在@PreUpdate/@postpdate调用就是这样 对于@PrePersist/@PostPersist,情况并非如此,因为该方法始终接收相同的实体实例 不确定您使用的是哪个版本的Hibernate,但我记得不久前我在为3.x版本做项目时注意到了这一点 更新
只是提醒您,当我在Upate之前/之后测试merge时,我发现merge()操作可以调用事件侦听器的唯一时间是在尚未持久化的新实体上调用它时。然后,它本身充当persist()操作,并调用@PrePersist注释类。因此,您可能永远无法通过该配置实现所需的功能。Foo是新实体还是以前已保存过?在我运行的测试中,它是新实体;我使用
merge
,因为在实际场景中,它可能是新的或现有的。Jira问题:您知道,作为merge参数提供的实例仍然是一个非托管实体,并且merge返回一个托管实体。因此,您在testMerge
中打印的实例将永远不会与侦听器中的实例相同!我知道@KlausGroenbaek,我在问为什么侦听器中的合并实例有一个空映射。Foo是一个新实体还是它以前已经保存过?在我运行的测试中,它是一个新实体;我使用merge
,因为在实际场景中,它可能是新的或现有的。Jira问题:您知道,作为merge参数提供的实例仍然是一个非托管实体,并且merge返回一个托管实体。因此,您在testMerge
中打印的实例将永远不会与侦听器中的实例相同!我知道@KlausGroenbaek,我在问为什么侦听器中的合并实例有一个空映射。我使用的是最新的5.2.6,是的,我发现实例不同。我不明白的是,如果映射正确地保存在数据库中,为什么会得到一个映射为空的实例。我会做更多的测试并在这里报告。试着使用em.persist(..)看看是否得到了实际的实例。稍后我会做更多的测试,我会将@PrePersist
和@PreUpdate
分开,似乎对新实体调用了@PrePersist
方法,但与您所说的实例不同:使用不同的实例,其中映射为空。好的,使用em.persist
而不是em.merge
触发具有相同实例和填充映射的@PrePersist
。不幸的是,在合并时,我也需要侦听器中的映射,我无法理解它为什么不在那里…解决@PreUpdate
调用添加@Version
字段。但是,回调中仍然没有映射…我将在Hibernate Jira中引发一个问题。我使用最新的5.2.6,是的,我发现实例不同。我不明白的是,如果映射正确地保存在数据库中,为什么会得到一个映射为空的实例。我会做更多的测试并在这里报告。试着使用em.persist(..)看看是否得到了实际的实例。稍后我会做更多的测试,我会将@PrePersist
和@PreUpdate
分开,似乎对新实体调用了@PrePersist
方法,但与您所说的实例不同:使用不同的实例,其中映射为空。好的,使用em.persist
而不是em.merge
触发具有相同实例和填充映射的@PrePersist
。不幸的是,在合并时,我也需要侦听器中的映射,我无法理解它为什么不在那里…解决@PreUpdate
调用添加@Version
字段。但是,回调中仍然没有映射…我将在Hibernate Jira中引发一个问题。
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'