unsaved
value是表示一個對象是新的還是舊的
如果unsaved
value=none 那麼就是新的
就會被insert到數據庫中
如果unsaved
value=any 就是說明對象是從數據庫中load的
被update到數據庫中
我的問題是
unsaved
value是由我們來強制說明這個對象是新的還是舊的
那如果我把一個對象的unsaved
value設置為any
那我要new 一個對象
把他save到數據庫中
怎麼做呢?我感覺這不是矛盾了嗎?主要是我們在寫配置文件的時候怎麼能說一個對象就一定是new的還是load的?
當你顯式的使用session
save()或者session
update()操作一個對象的時候
實際上是用不到unsaved
value的
某些情況下(父子表關聯保存)
當你在程序中並沒有顯式的使用save或者update一個持久對象
那麼Hibernate需要判斷被操作的對象究竟是一個已經持久化過的持久對象
是一個尚未被持久化過的內存臨時對象
例如
代碼:
Session session =
;
Transaction tx =
;
Parent parent = (Parent) session
load(Parent
class
id);
Child child = new Child();
child
setParent(parent);
child
setName(
sun
);
parent
addChild(child);
s
update(parent);
s
flush();
mit();
s
close();
在上例中
程序並沒有顯式的session
save(child); 那麼Hibernate需要知道child究竟是一個臨時對象
還是已經在數據庫中有的持久對象
如果child是一個新創建的臨時對象(本例中就是這種情況)
那麼Hibernate應該自動產生session
save(child)這樣的操作
如果child是已經在數據庫中有的持久對象
那麼Hibernate應該自動產生session
update(child)這樣的操作
因此我們需要暗示一下Hibernate
究竟child對象應該對它自動save還是update
在上例中
顯然我們應該暗示Hibernate對child自動save
而不是自動update
那麼Hibernate如何判斷究竟對child是save還是update呢?它會取一下child的主鍵屬性 child
getId()
這裡假設id是 java
lang
Integer類型的
如果取到的Id值和hbm映射文件中指定的unsave
value相等
那麼Hibernate認為child是新的內存臨時對象
發送save
如果不相等
那麼Hibernate認為child是已經持久過的對象
發送update
unsaved
value=
null
(默認情況
適用於大多數對象類型主鍵 Integer/Long/String/
)
當Hibernate取一下child的Id
取出來的是null(在上例中肯定取出來的是null)
和unsaved
value設定值相等
發送save(child)
當Hibernate取一下child的id
取出來的不是null
那麼和unsaved
value設定值不相等
發送update(child)
例如下面的情況
代碼:
Session session =
;
Transaction tx =
;
Parent parent = (Parent) session
load(Parent
class
id);
Child child = (Child) session
load(Child
class
childId);
child
setParent(parent);
child
setName(
sun
);
parent
addChild(child);
s
update(parent);
s
flush();
mit();
s
close();
child已經在數據庫中有了
是一個持久化的對象
不是新創建的
因此我們希望Hibernate發送update(child)
在該例中
Hibernate取一下child
getId()
和unsave
value指定的null比對一下
發現不相等
那麼發送update(child)
BTW: parent對象不需要操心
因為程序顯式的對parent有load操作和update的操作
不需要Hibernate自己來判斷究竟是save還是update了
我們要注意的只是child對象的操作
另外unsaved
value是定義在Child類的主鍵屬性中的
代碼:
<class name=
Child
table=
child
>
<id column=
id
name=
id
type=
integer
unsaved
value=
null
>
<generator class=
identity
/>
</id>
</class>
如果主鍵屬性不是對象型
而是基本類型
如int/long/double/
那麼你需要指定一個數值型的unsaved
value
例如
代碼:
unsaved
null=
在此提醒大家
很多人以為對主鍵屬性定義為int/long
比定義為Integer/Long運行效率來得高
認為基本類型不需要進行對象的封裝和解構操作
因此喜歡把主鍵定義為int/long的
但實際上
Hibernate內部總是把主鍵轉換為對象型進行操作的
就算你定義為int/long型的
Hibernate內部也要進行一次對象構造操作
返回給你的時候
還要進行解構操作
效率可能反而低也說不定
因此大家一定要扭轉一個觀點
在Hibernate中
主鍵屬性定義為基本類型
並不能夠比定義為對象型效率來的高
而且也多了很多麻煩
因此建議大家使用對象型的Integer/Long定義主鍵
unsaved
value=
none
和
unsaved
value=
any
主主要用在主鍵屬性不是通過Hibernate生成
而是程序自己setId()的時候
在這裡多說一句
強烈建議使用Hibernate的id generator
或者你可以自己擴展Hibernate的id generator
特別注意不要使用有實際含義的字段當做主鍵來用!例如用戶類User
很多人喜歡用用戶登陸名稱做為主鍵
這是一個很不好的習慣
當用戶類和其他實體類有關聯關系的時候
萬一你需要修改用戶登陸名稱
一改就需要改好幾張表中的數據
偶合性太高
而如果你使用無業務意義的id generator
那麼修改用戶名稱
就只修改user表就行了
由這個問題引申出來
如果你嚴格按照這個原則來設計數據庫
那麼你基本上是用不到手工來setId()的
你用Hibernate的id generator就OK了
因此你也不需要了解當
unsaved
value=
none
和
unsaved
value=
any
究竟有什麼含義了
如果你非要用assigned不可
那麼繼續解釋一下
unsaved
value=
none
的時候
由於不論主鍵屬性為任何值
都不可能為none
因此Hibernate總是對child對象發送update(child)
unsaved
value=
any
的時候
由於不論主鍵屬性為任何值
都肯定為any
因此Hibernate總是對child對象發送save(child)
大多數情況下
你可以避免使用assigned
只有當你使用復合主鍵的時候不得不手工setId()
這時候需要你自己考慮究竟怎麼設置unsaved
value了
根據你自己的需要來定
BTW: Gavin King強烈不建議使用composite
id
強烈建議使用UserType
因此
如果你在系統設計的時候
遵循如下原則
使用Hibernate的id generator來生成無業務意義的主鍵
不使用有業務含義的字段做主鍵
不使用assigned
使用對象類型(String/Integer/Long/
)來做主鍵
而不使用基礎類型(int/long/
)做主鍵
不使用composite
id來處理復合主鍵的情況
而使用UserType來處理該種情況
那麼你永遠用的是unsaved
value=
null
不可能用到any/none/
了
From:http://tw.wingwit.com/Article/program/Java/Javascript/201311/25399.html