2017-01-23 87 views
1

我遇到一个奇怪的问题:我有一个实体,该类的听众,休眠@更新前/ @ 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); 
    } 

} 

,然后当我执行testMerge我得到这个输出(更新与SQL调试):

[email protected] 
1 
[email protected] 
0 
Hibernate: insert into Foo values () 
Hibernate: insert into Foo_map (Foo_id, map_KEY, map) values (?, ?, ?) // 1, 'foo', 'test' 

所以地图获取数据库上的正确保存,但传递到听者的实体有一个空的地图。发生什么事?

UPDATE:JIRA问题和测试用例 相关JIRA问题:https://hibernate.atlassian.net/browse/HHH-11414 和测试用例:https://github.com/heruan/hibernate-testcase/tree/HHH-11414

+0

是Foo一个新的实体或它已被保存过吗? –

+0

在测试中,我运行它是一个新的实体;我使用'merge',因为在真实场景中它可能是一个新的或现有的。 –

+0

Jira问题:https://hibernate.atlassian.net/browse/HHH-11414 –

回答

0

那是一个很微妙的,但如果您调试testMerge代码和监听方法,您不妨了解一下Foo的实际情况是不同的。 现在,@PreUpdate/@PostUpdate调用就是这种情况。

对于@PrePersist/@PostPersist,情况并非如此,因为该方法总是接收实体的同一个实例。

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

更新

只是提醒你,因为我在测试沿室内用前/后Upate合并,我发现唯一的一次,合并()操作可以调用事件侦听器是当它在尚未持久的新实体上调用。然后它本身充当persist()操作,并调用@PrePersist带注释的类。所以你可能永远无法实现你想要的配置。

+0

我是最新的5.2.6,是的,我发现实例是不同的。我不明白的是为什么我得到一个空地图的实例,如果地图然后正确地保存在数据库中。我会做更多的测试并在这里报告。 –

+0

尝试使用em.persist(..)只是为了看看你是否得到了实际的实例。我会在 –

+0

后面做更多的测试,我分割了@PrePersist和@PreUpdate,看起来对于新实体来说,@ @ PrePersist方法被调用,但是不像你说的那样使用相同的实例: ,地图是空的。 –