Hibernate映像文件指明了Person的id字段代表了數據庫中的ID列(也就是說它是PERSON表的主鍵)包含在id標簽中的unsavedvalue=null屬性告訴Hibernate使用id字段來判斷一個Person對象之前是否被保存過ORM框架必須依靠這個來判斷保存一個對象的時候應該使用SQL的INSERT字句還是UPDATE字句在這個例子中Hibernate假定一個新對象的id字段一開始為null值當它第一次被保存時才id才被賦予一個值generator標簽告訴Hibernate當對象第一次保存時應該從哪裡獲得指派的id在這個例子中Hibernate使用數據庫序列作為產生唯一id的來源最後version標簽告訴Hibernate使用Person對象的version字段進行並發控制Hibernate將會執行樂觀鎖方案(optimistic locking scheme)根據這個方案Hibernate在保存對象之前會檢查對比對象的version值和數據庫中相應數據的version值
我們的Person對象還缺少的是equals()方法和hashCode()方法的實現既然這是一個持久化對象我們並不想依賴於這兩個方法的缺省實現因為缺省實現並不能分辨代表數據庫中同一實體的不同實例一種簡單而又顯然的實現方法是利用id字段來進行equal()方法的比較以及生成hashCode()方法的結果
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Person))
return false;
Person other = (Person)o;
if (id == other
getId()) return true;
if (id == null) return false;
// equivalence by id
return id
equals(other
getId());
}
public int hashCode() {
if (id != null) {
return id
hashCode();
}
else {
return super
hashCode();
}
}
不走運的是這個實現存在著問題當我們首次創建Person對象的時候id的值是null這意味著任何兩個沒有被保存的Person對象都將被認為是等價的如果我們想創建一個Person對象並把它放到Set數據結構中再創建了一個完全不同的Person對象也把它放到同一個Set裡面事實上第個Person對象並不能被加入這是因為Set會斷定所有未經保存的對象都是相同的
你可能會試探著去實現一個只使用被設置過的id的equals()方法畢竟如果兩個對象都沒有被保存過我們可以假定它們是不同的對象這是因為在它們被保存到數據庫的時候它們會被賦予不同的主鍵
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || !(o instanceof Person)) return false;
Person other = (Person)o;
// unsaved objects are never equal
if (id == null || other
getId() == null) return false;
return id
equals(other
getId());
}
這裡有個隱藏的問題Java的Collection框架在它的生命周期中需要基於不變字段的equals()和hashCode()方法換句話來說當一個對象處在Collection中的時候你不可以改變equals()和hashCode()的返回值舉個例子下面這段程序
Person p = new Person();
Set set = new HashSet();
set
add(p);
System
out
println(set
contains(p));
p
setId(new Long(
));
System
out
println(set
contains(p));
打印結果: true false
對setcontains(p)的第次調用返回了false是因為Set再也找不到p了用書面化的語言講Set丟失了這個對象!這是因為當對象在Set中時我們改變了hashCode()的返回值
[] [] [] [] []
From:http://tw.wingwit.com/Article/program/Java/ky/201311/28969.html