unsave-value:用來控制是save還是update對(duì)象。
當(dāng)你顯式的使用session.save()或者session.update()操作一個(gè)對(duì)象的時(shí)候,實(shí)際上是用不到unsaved-value的。某些情況下(父子表關(guān)聯(lián)保存),當(dāng)你在程序中并沒有顯式的使用save或者update一個(gè)持久對(duì)象,那么Hibernate需要判斷被操作的對(duì)象究竟是一個(gè)已經(jīng)持久化過的持久對(duì)象,是一個(gè)尚未被持久化過的內(nèi)存臨時(shí)對(duì)象。例如:

 1Session session = ;   
 2Transaction tx = ;   
 3  
 4Parent parent = (Parent) session.load(Parent.class, id);   
 5  
 6Child child = new Child();   
 7child.setParent(parent);   
 8child.setName("sun");   
 9  
10parent.addChild(child);   
11s.update(parent);   
12  
13s.flush();   
14tx.commit();   
15s.close();  

在上例中,程序并沒有顯式的session.save(child); 那么Hibernate需要知道child究竟是一個(gè)臨時(shí)對(duì)象,還是已經(jīng)在數(shù)據(jù)庫中有的持久對(duì)象。如果child是一個(gè)新創(chuàng)建的臨時(shí)對(duì)象(本例中就是這種情況),那么Hibernate應(yīng)該自動(dòng)產(chǎn)生session.save(child)這樣的操作,如果child是已經(jīng)在數(shù)據(jù)庫中有的持久對(duì)象,那么Hibernate應(yīng)該自動(dòng)產(chǎn)生session.update(child)這樣的操作。

因此我們需要暗示一下Hibernate,究竟child對(duì)象應(yīng)該對(duì)它自動(dòng)save還是update。在上例中,顯然我們應(yīng)該暗示Hibernate對(duì)child自動(dòng)save,而不是自動(dòng)update。那么Hibernate如何判斷究竟對(duì)child是save還是update呢?它會(huì)取一下child的主鍵屬性 child.getId() ,這里假設(shè)id是 java.lang.Integer類型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate認(rèn)為child是新的內(nèi)存臨時(shí)對(duì)象,發(fā)送save,如果不相等,那么Hibernate認(rèn)為child是已經(jīng)持久過的對(duì)象,發(fā)送update。

unsaved-value="null" (默認(rèn)情況,適用于大多數(shù)對(duì)象類型主鍵 Integer/Long/String/...)

當(dāng)Hibernate取一下child的Id,取出來的是null(在上例中肯定取出來的是null),和unsaved-value設(shè)定值相等,發(fā)送save(child)

當(dāng)Hibernate取一下child的id,取出來的不是null,那么和unsaved-value設(shè)定值不相等,發(fā)送update(child)

例如下面的情況:

 1Session session = ;   
 2Transaction tx = ;   
 3  
 4Parent parent = (Parent) session.load(Parent.class, id);   
 5Child child = (Child) session.load(Child.class, childId);   
 6  
 7child.setParent(parent);   
 8child.setName("sun");   
 9  
10parent.addChild(child);   
11s.update(parent);   
12  
13s.flush();   
14tx.commit();   
15s.close();  

child已經(jīng)在數(shù)據(jù)庫中有了,是一個(gè)持久化的對(duì)象,不是新創(chuàng)建的,因此我們希望Hibernate發(fā)送update(child),在該例中,Hibernate取一下child.getId(),和unsave-value指定的null比對(duì)一下,發(fā)現(xiàn)不相等,那么發(fā)送update(child)。

parent對(duì)象不需要操心,因?yàn)槌绦蝻@式的對(duì)parent有l(wèi)oad操作和update的操作,不需要Hibernate自己來判斷究竟是save還是update了。我們要注意的只是child對(duì)象的操作。另外unsaved-value是定義在Child類的主鍵屬性中的。


 
1<class name="Child" table="child">  
2<id column="id" name="id" type="integer" unsaved-value="null">  
3  <generator class="identity"/>  
4</id>  
5   
6</class>  
7

如果主鍵屬性不是對(duì)象型,而是基本類型,如int/long/double/...,那么你需要指定一個(gè)數(shù)值型的unsaved-value,例如:
1unsaved-value="0"

很多人以為對(duì)主鍵屬性定義為int/long,比定義為Integer/Long運(yùn)行效率來得高,認(rèn)為基本類型不需要進(jìn)行對(duì)象的封裝和解構(gòu)操作,因此喜歡把主鍵定義為int/long的。但實(shí)際上,Hibernate內(nèi)部總是把主鍵轉(zhuǎn)換為對(duì)象型進(jìn)行操作的,就算你定義為int/long型的,Hibernate內(nèi)部也要進(jìn)行一次對(duì)象構(gòu)造操作,返回給你的時(shí)候,還要進(jìn)行解構(gòu)操作,效率可能反而低也說不定。因此大家一定要扭轉(zhuǎn)一個(gè)觀點(diǎn),在Hibernate中,主鍵屬性定義為基本類型,并不能夠比定義為對(duì)象型效率來的高,而且也多了很多麻煩,因此建議大家使用對(duì)象型的Integer/Long定義主鍵.