国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

Java中關(guān)于unsaved-value的問(wèn)題

2019-11-18 15:05:06
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

  unsaved-value是表示一個(gè)對(duì)象是新的還是舊的,假如unsaved-value=none 那么就是新的,就會(huì)被insert到數(shù)據(jù)庫(kù)中,假如unsaved-value=any 就是說(shuō)明對(duì)象是從數(shù)據(jù)庫(kù)中l(wèi)oad的,被update到數(shù)據(jù)庫(kù)中。
  
  我的問(wèn)題是:unsaved-value是由我們來(lái)強(qiáng)制說(shuō)明這個(gè)對(duì)象是新的還是舊的,那假如我把一個(gè)對(duì)象的unsaved-value設(shè)置為any,那我要new 一個(gè)對(duì)象,把他save到數(shù)據(jù)庫(kù)中,怎么做呢?我感覺(jué)這不是矛盾了嗎?主要是我們?cè)趯懪渲梦募臅r(shí)候怎么能說(shuō)一個(gè)對(duì)象就一定是new的還是load的?
  
  當(dāng)你顯式的使用session.save()或者session.update()操作一個(gè)對(duì)象的時(shí)候,實(shí)際上是用不到unsaved-value的。某些情況下(父子表關(guān)聯(lián)保存),當(dāng)你在程序中并沒(méi)有顯式的使用save或者update一個(gè)持久對(duì)象,那么Hibernate需要判定被操作的對(duì)象究竟是一個(gè)已經(jīng)持久化過(guò)的持久對(duì)象,是一個(gè)尚未被持久化過(guò)的內(nèi)存臨時(shí)對(duì)象。例如:
  
  代碼:
  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();
  
  
  在上例中,程序并沒(méi)有顯式的session.save(child); 那么Hibernate需要知道child究竟是一個(gè)臨時(shí)對(duì)象,還是已經(jīng)在數(shù)據(jù)庫(kù)中有的持久對(duì)象。假如child是一個(gè)新創(chuàng)建的臨時(shí)對(duì)象(本例中就是這種情況),那么Hibernate應(yīng)該自動(dòng)產(chǎn)生session.save(child)這樣的操作,假如child是已經(jīng)在數(shù)據(jù)庫(kù)中有的持久對(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)持久過(guò)的對(duì)象,發(fā)送update。
  
  unsaved-value="null" (默認(rèn)情況,適用于大多數(shù)對(duì)象類型主鍵 Integer/Long/String/...)
  
  當(dāng)Hibernate取一下child的Id,取出來(lái)的是null(在上例中肯定取出來(lái)的是null),和unsaved-value設(shè)定值相等,發(fā)送save(child)
  
  當(dāng)Hibernate取一下child的id,取出來(lái)的不是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();
  
  child已經(jīng)在數(shù)據(jù)庫(kù)中有了,是一個(gè)持久化的對(duì)象,不是新創(chuàng)建的,因此我們希望Hibernate發(fā)送update(child),在該例中,Hibernate取一下child.getId(),和unsave-value指定的null比對(duì)一下,發(fā)現(xiàn)不相等,那么發(fā)送update(child)。
  
  BTW: parent對(duì)象不需要操心,因?yàn)槌绦蝻@式的對(duì)parent有l(wèi)oad操作和update的操作,不需要Hibernate自己來(lái)判定究竟是save還是update了。我們要注重的只是child對(duì)象的操作。另外unsaved-value是定義在Child類的主鍵屬性中的。
  
  代碼:
  <class name="Child" table="child">
  <id column="id" name="id" type="integer" unsaved-value="null">
   <generator class="identity"/>
  </id>
  ...
  </class>
  
  假如主鍵屬性不是對(duì)象型,而是基本類型,如int/long/double/...,那么你需要指定一個(gè)數(shù)值型的unsaved-value,例如:
  
  代碼:
  unsaved-null="0"
  
  在此提醒大家,很多人以為對(duì)主鍵屬性定義為int/long,比定義為Integer/Long運(yùn)行效率來(lái)得高,認(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)操作,效率可能反而低也說(shuō)不定。因此大家一定要扭轉(zhuǎn)一個(gè)觀點(diǎn),在Hibernate中,主鍵屬性定義為基本類型,并不能夠比定義為對(duì)象型效率來(lái)的高,而且也多了很多麻煩,因此建議大家使用對(duì)象型的Integer/Long定義主鍵。
  
  unsaved-value="none"和
  unsaved-value="any"
  
  主主要用在主鍵屬性不是通過(guò)Hibernate生成,而是程序自己setId()的時(shí)候。
  
  在這里多說(shuō)一句,強(qiáng)烈建議使用Hibernate的id generator,或者你可以自己擴(kuò)展Hibernate的id generator,非凡注重不要使用有實(shí)際含義的字段當(dāng)做主鍵來(lái)用!例如用戶類User,很多人喜歡用用戶登陸名稱做為主鍵,這是一個(gè)很不好的習(xí)慣,當(dāng)用戶類和其他實(shí)體類有關(guān)聯(lián)關(guān)系的時(shí)候,萬(wàn)一你需要修改用戶登陸名稱,一改就需要改好幾張表中的數(shù)據(jù)。偶合性太高,而假如你使用無(wú)業(yè)務(wù)意義的id generator,那么修改用戶名稱,就只修改user表就行了。
  
  由這個(gè)問(wèn)題引申出來(lái),假如你嚴(yán)格按照這個(gè)原則來(lái)設(shè)計(jì)數(shù)據(jù)庫(kù),那么你基本上是用不到手工來(lái)setId()的,你用Hibernate的id generator就OK了。因此你也不需要了解當(dāng)
  
  unsaved-value="none"和
  unsaved-value="any"
  
  究竟有什么含義了。假如你非要用assigned不可,那么繼續(xù)解釋一下:
  
  unsaved-value="none" 的時(shí)候,由于不論主鍵屬性為任何值,都不可能為none,因此Hibernate總是對(duì)child對(duì)象發(fā)送update(child)
  
  unsaved-value="any" 的時(shí)候,由于不論主鍵屬性為任何值,都肯定為any,因此Hibernate總是對(duì)child對(duì)象發(fā)送save(child)
  
  大多數(shù)情況下,你可以避免使用assigned,只有當(dāng)你使用復(fù)合主鍵的時(shí)候不得不手工setId(),這時(shí)候需要你自己考慮究竟怎么設(shè)置unsaved-value了,根據(jù)你自己的需要來(lái)定。
  
  BTW: Gavin King強(qiáng)烈不建議使用composite-id,強(qiáng)烈建議使用UserType。
  
  因此,假如你在系統(tǒng)設(shè)計(jì)的時(shí)候,遵循如下原則:
  
  1、使用Hibernate的id generator來(lái)生成無(wú)業(yè)務(wù)意義的主鍵,不使用有業(yè)務(wù)含義的字段做主鍵,不使用assigned。
  
  2、使用對(duì)象類型(String/Integer/Long/...)來(lái)做主鍵,而不使用基礎(chǔ)類型(int/long/...)做主鍵
  
  3、不使用composite-id來(lái)處理復(fù)合主鍵的情況,而使用UserType來(lái)處理該種情況。
  
  那么你永遠(yuǎn)用的是unsaved-value="null" ,不可能用到any/none/..了。

發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 泸溪县| 宣化县| 尉氏县| 方正县| 涿州市| 富锦市| 乡宁县| 黄大仙区| 石屏县| 眉山市| 昭通市| 望江县| 九寨沟县| 宁波市| 仪陇县| 绥江县| 潞西市| 威信县| 贺州市| 洪湖市| 西乌珠穆沁旗| 云阳县| 焦作市| 娱乐| 镇安县| 永康市| 老河口市| 阿拉善右旗| 临安市| 镇原县| 汤阴县| 城步| 财经| 苏州市| 上饶县| 和林格尔县| 文登市| 繁峙县| 蓝田县| 利川市| 毕节市|