Hibernate @ PreUpdate / @ PrePersist不一致

时间:2017-01-23 09:28:21

标签: 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
    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

1 个答案:

答案 0 :(得分:0)

这是一个棘手的问题,但是如果你调试testMerge代码和监听器方法,你可能会发现Foo的实际实例是不同的。 现在是@PreUpdate / @PostUpdate调用的情况。

对于@PrePersist / @PostPersist,情况并非如此,因为该方法始终接收相同的实体实例。

不确定您使用的是哪个版本的Hibernate,但我记得当时我正在为3.x版本做一个项目。

<强>更新

只是提醒你,因为我正在使用Pre / Post Upate测试合并,我发现唯一的一次,merge()操作可以调用事件监听器是在新实体上调用它时尚未坚持。然后它作为一个persist()操作本身,并调用@PrePersist注释类。因此,您可能永远无法通过该配置实现您所寻求的目标。