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

Java 中關於 unsaved-value 的問題

2013-11-23 17:56:50  來源: Javascript 

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

  • 下一篇文章:
  • 推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.