引用 http://blog.csdn.net/chinarefers/archive/2005/01/20/261252.aspx ywang的提問:
unsaved-value是表示一個對象是新的還是舊的,如果unsaved-value=none 那么就是新的,就會被insert到數(shù)據(jù)庫中,如果unsaved-value=any 就是說明對象是從數(shù)據(jù)庫中l(wèi)oad的,被update到數(shù)據(jù)庫中。 我的問題是:unsaved-value是由我們來強制說明這個對象是新的還是舊的,那如果我把一個對象的unsaved-value設(shè)置為any,那我要new 一個對象,把他save到數(shù)據(jù)庫中,怎么做呢?我感覺這不是矛盾了嗎?主要是我們在寫配置文件的時候怎么能說一個對象就一定是new的還是load的? 我查過過去的一些帖子,都是講到unsaved-value是什么表示什么意思,我還不是不懂,希望大家教我。 robbin的回答: 當(dāng)你顯式的使用session.save()或者session.update()操作一個對象的時候,實際上是用不到unsaved-value的。某些情況下(父子表關(guān)聯(lián)保存),當(dāng)你在程序中并沒有顯式的使用save或者update一個持久對象,那么Hibernate需要判斷被操作的對象究竟是一個已經(jīng)持久化過的持久對象,是一個尚未被持久化過的內(nèi)存臨時對象。例如: 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();tx.commit();s.close(); 因此我們需要暗示一下Hibernate,究竟child對象應(yīng)該對它自動save還是update。在上例中,顯然我們應(yīng)該暗示Hibernate對child自動save,而不是自動update。那么Hibernate如何判斷究竟對child是save還是update呢?它會取一下child的主鍵屬性 child.getId() ,這里假設(shè)id是 java.lang.Integer類型的。如果取到的Id值和hbm映射文件中指定的unsave-value相等,那么Hibernate認為child是新的內(nèi)存臨時對象,發(fā)送save,如果不相等,那么Hibernate認為child是已經(jīng)持久過的對象,發(fā)送update。 unsaved-value="null" (默認情況,適用于大多數(shù)對象類型主鍵 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) 例如下面的情況: 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();tx.commit();s.close(); BTW: parent對象不需要操心,因為程序顯式的對parent有l(wèi)oad操作和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> unsaved-null="0" unsaved-value="none"和 unsaved-value="any" 主主要用在主鍵屬性不是通過Hibernate生成,而是程序自己setId()的時候。 在這里多說一句,強烈建議使用Hibernate的id generator,或者你可以自己擴展Hibernate的id generator,特別注意不要使用有實際含義的字段當(dāng)做主鍵來用!例如用戶類User,很多人喜歡用用戶登陸名稱做為主鍵,這是一個很不好的習(xí)慣,當(dāng)用戶類和其他實體類有關(guān)聯(lián)關(guān)系的時候,萬一你需要修改用戶登陸名稱,一改就需要改好幾張表中的數(shù)據(jù)。偶合性太高,而如果你使用無業(yè)務(wù)意義的id generator,那么修改用戶名稱,就只修改user表就行了。 由這個問題引申出來,如果你嚴格按照這個原則來設(shè)計數(shù)據(jù)庫,那么你基本上是用不到手工來setId()的,你用Hibernate的id generator就OK了。因此你也不需要了解當(dāng) unsaved-value="none"和 unsaved-value="any" 究竟有什么含義了。如果你非要用assigned不可,那么繼續(xù)解釋一下: unsaved-value="none" 的時候,由于不論主鍵屬性為任何值,都不可能為none,因此Hibernate總是對child對象發(fā)送update(child) unsaved-value="any" 的時候,由于不論主鍵屬性為任何值,都肯定為any,因此Hibernate總是對child對象發(fā)送save(child) 大多數(shù)情況下,你可以避免使用assigned,只有當(dāng)你使用復(fù)合主鍵的時候不得不手工setId(),這時候需要你自己考慮究竟怎么設(shè)置unsaved-value了,根據(jù)你自己的需要來定。 BTW: Gavin King強烈不建議使用composite-id,強烈建議使用UserType。 因此,如果你在系統(tǒng)設(shè)計的時候,遵循如下原則: 1、使用Hibernate的id generator來生成無業(yè)務(wù)意義的主鍵,不使用有業(yè)務(wù)含義的字段做主鍵,不使用assigned。 2、使用對象類型(String/Integer/Long/...)來做主鍵,而不使用基礎(chǔ)類型(int/long/...)做主鍵 3、不使用composite-id來處理復(fù)合主鍵的情況,而使用UserType來處理該種情況。 那么你永遠用的是unsaved-value="null" ,不可能用到any/none/..了。
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=261252
|