熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

別讓Hibernate偷走了你的標識符[3]

2013-11-23 20:43:25  來源: Java開源技術 

  當你想要創建一個將其它域對象保存在SetMap或是List裡面的域對象時這是一個問題為了解決這個問題你必須為你的所有對象提供一種equals()和hashCode()的實現這種實現能夠保證在它們在對象保存前後正確工作並且當對象在內存中時(返回值)不會改變Hibernate參考文檔提供了以下的建議

  不要使用數據庫標識符來實現等價的判斷而應該使用商業鍵值(business key)一種唯一的通常不改變的屬性的結合體當一個buk不可序列化對象(transient object)被持久化的時候數據庫標識符會發生改變當一個不可序列化實例(常常和detached instances在一起)被包含在一個Set裡面時哈希值的改變會破壞Set的從屬關系商業鍵值的屬性並不要求和數據庫主鍵一樣穩定你只要保證當對象在某個Set中時它們的穩定性

  我們推薦判斷商業鍵值的等價性來實現equals()和hashCode()兩個方法這意味著equals()方法只比較能夠區分現實世界中的實例的商業鍵值(某個候選碼)的屬性(Hibernate 參考文檔 v )

  換句話說equals()和hashCode()使用商業鍵值進行處理而對象使用Hibernate生成的鍵值作為id值這要求對於每個對象有一個相關的不會改變的商業鍵值可是並不是每個對象類型都有這樣的一種鍵這時候你可能會嘗試使用會改變但不時常改變的字段這和商業鍵值不必和數據庫主鍵一樣穩定的思想相吻合當對象在Collection中時候如果這種鍵不改變那它們似乎就足夠好這是一種危險的主張這意味著你的應用程序可能不會崩潰但是前提是沒有人在特定的情況下更新了特定的字段所以應當有一種更好的解決方案而它確實也存在 試圖創建和維護在對象和數據庫行兩者間有著分離的定義的標識符是目前為止討論的所有問題的根源如果我們統一所有標識符的形式這些問題都將不復存在也就時說作為以數據庫為中心和以對象為中心的標識符的替代品我們應該創建一種通用的特定於實體的ID來代表數據實體這種ID應該在數據第一次輸入的時候產生無論一個唯一數據實體是保存在數據庫是作為對象駐留在內存還時存貯在其它格式的介質中這個通用ID都應該可以識別它通過使用數據實體第一次創建時指派的ID我們可以安全的回到我們對equals()和hashCode()的原始定義它們只是簡單地使用了這個id

public class Person {
 // assign an id as soon as possible
 private String id = IdGeneratorcreateId();
 private Integer version;
 public String getId() { return id; }
 public void setId(String id) {
thisid = id;
 }
 public Integer getVersion() {
return version;
 }
 public void setVersion(Integer version) {
thisversion = version;
 }
 // Personspecific fields and behavior here
 public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Person)) return false;
Person other = (Person)o;
if (id == null) return false;
return idequals(othergetId());
 }
 public int hashCode() {
if (id != null) {
 return idhashCode();
} else {
 return superhashCode();
}
 }
}

  這個例子使用id作為equals()方法判斷等價的標准以及hashCode()返回哈希值的來源這就簡單了許多但是要讓它正常工作我們需要兩樣東西首先我們需要保證每個對象在被保存之前都有一個id值在這個例子裡當id變量被聲明的時候它就被指派了一個值其次我們需要一種判斷這個對象是新生成的還是之前保存過的的手段在我們最早的例子中Hibernate檢查id字段是否為空來判斷對象是否時新生成的既然我們的對象id永遠不為空這個方法顯然不再有效為了解決這個問題我們可以很容易的配置Hibernate讓它檢查version字段而不是id字段是否為空version字段是一個更為恰當的用來判斷你的對象是否被保存過的指示器

[]  []  []  []  []  


From:http://tw.wingwit.com/Article/program/Java/ky/201311/28967.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.