2015-04-29 27 views
2

爲了討論起見,請考慮以下Hibernate的註釋對象:任何獲取HibernateInterceptor中新實體實例生成的id的方法?

@Entity 
public class TestModelObject { 
    @Id 
    @GeneratedValue 
    @Column 
    private int id; 

    @Column 
    private String name; 

    public int getId() { 
     return id; 
    } 

    public void setId(int id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    }  
} 

的問題是,你怎麼能獲取生成的ID值,對於一個新的實例,通過器HibernateInterceptor(通過session.save堅持)?我將概述一些可用的方法,這是我測試過,並解釋爲什麼每個人是不夠的:

  • onSave - 不工作,因爲ID爲空,用於插入一個新的實例。這是有道理的,因爲在這種情況下,Hibernate並不知道ID,因爲它是在RDBMS插入時生成的。
  • postFlush - 這有我以後的數據,但無法使用。它包含了許多正在刷新的對象的迭代器,包括你感興趣的對象,但沒有合理簡單的方法從這個迭代器中取出新保存的實例,而沒有執行像添加「標記」布爾和填充它在onSave上,並在這裏尋找它。
  • instantiate - 這種有數據,但無法使用。每次Hibernate實例化一個對象時它都會被調用,並且它包含了id作爲參數。它肯定會被調用一個新保留的實體,但沒有合理的關聯實體本身,因爲它只包括類名稱,類型(在這種情況下是POJO)和id。

我一直希望得到類似於postSave的東西,它會在插入完成後觸發,爲新創建的實體創建,它會生成生成的id。但我無法找到這樣的事情。有沒有什麼辦法可以完成我想要做的事情,而不是訴諸諸如保存兩次以及在第二次保存時執行攔截器「工作」的攻擊?

回答

0

你試過JPA Entity Listeners
使用實體監聽您可以註釋你的實體類是這樣的:

@Entity 
@EntityListeners({ UserEntityListener.class, UserPasswordValidator.class }) 
public class Book { 

    @Id 
    @GeneratedValue 
    @Column(name = "ID") 
    private Long id; 

    @Columnt(name = "LOGIN") 
    private String login; 

    @Column(name = "PASSWORD") 
    private String password; 

    // getters, setters ommited 

} 

然後你實現你的聽衆:

public class BookEntityListener { 

    @PostPersist 
    public void postPersist(User user) { 
     // do your logic 
    } 

} 

public class PasswordValidator { 

    @PrePersist 
    @PreUpdate 
    public void validatePassword(User user) { 
     if (passwordTooShort(user.password()) 
      throw new PersistenceException("Password too short"); 
    } 

} 

有多個生命週期標註可供選擇:

  • @PrePersist
    在實體管理器持久化操作之前執行實際上是 執行或級聯。此調用與持久操作同步。

  • @PostPersist
    實體管理器後,執行持續操作實際執行或 級聯。在數據庫INSERT執行後調用此調用。

  • @PreRemove
    實體管理器之前執行刪除操作已被執行 級聯。此調用與刪除操作同步。

  • @PostRemove
    實體管理器刪除操作後執行實際上是執行或級聯 。此調用與刪除 操作同步。

  • @PreUpdate
    執行數據庫前UPDATE操作。

  • @PostUpdate
    執行數據庫後UPDATE操作。

  • @PostLoad
    的實體之後執行已經加載到當前 持久性上下文或實體已被刷新。

+0

您是否知道「@ PostPersist」和「@ PostUpdate」是否觸發只有映射集合的實體更改?有一個[打開Hibernate的bug](https://hibernate.atlassian.net/browse/HHH-4897)這裏的'onFlushDirty'沒有被調用,如果底層的問題也影響了實體監聽器,那麼我無法使用它們。如果你不知道,那麼我可以測試它;謝謝。 –

+0

不,對不起。也必須測試這個以及... – npe

+0

但是,如果您在子實體中映射的父對象具有「一對一」關係,那麼您也可以在子實體上進行偵聽,並通過從子項調用來獲得父對象。 – npe