2017-01-23 30 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方法被調用,但是不像你說的那樣使用相同的實例: ,地圖是空的。 –