自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Hibernate中cascade與inverse屬性詳解

開發(fā) 后端
本篇文章主要講解關(guān)于Hibernate中cascade與inverse的理解。希望對大家有所幫助。

關(guān)于Hibernate中 cascade 與 inverse 的理解。

您買的Hibernate書是哪一本呢? 孫衛(wèi)琴的精通Hibernate,還是 深入淺出Hibernate還是那本。。。

我是兩本都買了,總體來說還可以,但是,有的地方講的比較書面化,比如inverse這屬性。

在學(xué)習(xí)Hibernate的過程中最不好理解的就是這兩個(gè)屬性了。

(我當(dāng)初學(xué)習(xí)Hibernate的時(shí)候,發(fā)現(xiàn)網(wǎng)上介紹這兩個(gè)屬性的文章倒是不少,但是,居然有好多都是轉(zhuǎn)帖。。。還有的就是 照書搬~~-_-!!!)。。。

據(jù)個(gè)例子:書上說inverse=false時(shí),由主控方維持關(guān)系。。。

由于我也是初學(xué)者。。。再加上語文水平偏低。。。不理解“維持關(guān)系是啥意思”囧~

提示:

(1)如果:您不了解Hibernate的one-to-many或many-to-one的概念。

(2)如果:你不了解Hibernate的“自由態(tài)”“持久態(tài)”“游離態(tài)”的概念。

(3)如果:您不了解Hibernate中的“臟數(shù)據(jù)”的概念。

(4)如果:您對Hibernate中Session緩存,沒有初步了解的話。

(在Hibernate中調(diào)用save進(jìn)行存儲數(shù)據(jù)的時(shí)候,并不是馬上就對數(shù)據(jù)庫進(jìn)行insert操作,而是會將其“數(shù)據(jù)對象(vo)”納入Hibernate的Session緩存。)

在上面的4條提示中,如果您對其中的某一條,不是很清楚的話。希望請先了解有關(guān)知識。

否則,可能您將 “無法或很難”理解 cascade 或 inverse 這2個(gè)屬性。

首相,cascade 與 inverse 這兩個(gè)屬性,其實(shí)是完全不同的兩個(gè)東西,想要了解他們各自的“用途與區(qū)別”,詳見如下介紹:

這里有兩個(gè)表:

(1)class (班級表)

相應(yīng)字段:

cid varchar(32) 主鍵 not-null (班級id)

cname varchar(16) not-null (班級名稱)

(2)student (學(xué)生表)

相應(yīng)字段:

sid varchar(32) 主鍵 not-null (學(xué)生id)

sname varchar(16) not-null (學(xué)生姓名)

class_id varchar(32) not-null (學(xué)生所屬班級)

一個(gè)班級(class)對應(yīng)多個(gè)學(xué)生(student),所以班級表(class)就是“one-to-many”端

反之student就是many-to-one

 

  1. //--------Class類的代碼--------  
  2.  
  3. public class Class implements.....  
  4.  
  5. {  
  6.  
  7. private cId = "";  
  8.  
  9. private cName = "";  
  10.  
  11. private students = java.util.HashMap();  
  12.  
  13. // 省略對應(yīng)的 geter setter  
  14.  
  15. }  
  16.  
  17. //--------Class.hbm.xml--------  
  18.  
  19.  
  20.  
  21. <class name="lcx.vo.Class" table="class" 
  22.  
  23.    catalog="demo">  
  24.  
  25.    "cid" type="java.lang.String">  
  26.  
  27.     "cid" length="32" />  
  28.  
  29.     class="uuid.hex" />  
  30.  
  31.      
  32.  
  33.    "name" type="java.lang.String">  
  34.  
  35.     "cname" length="16" not-null="true" />  
  36.  
  37.      
  38.  
  39.     
  40.  
  41.    "students" table="student" cascade="save-update">  
  42.  
  43.     "class" />  
  44.  
  45.     class="lcx.vo.Student" />  
  46.  
  47.       
  48.  
  49. class>  
  50.  
  51.  
  52.  
  53. //--------Student類的代碼;*******  
  54.  
  55. public class Student implements.....  
  56.  
  57. {  
  58.  
  59. private sId = "";  
  60.  
  61. private sName = "";  
  62.  
  63. private Class class = null;  
  64.  
  65. // 省略對應(yīng)的 geter setter  
  66.  
  67. }  
  68.  
  69. // Student.hbm.xml  
  70.  
  71.  
  72.  
  73. <class name="lcx.vo.Student" table="student" catalog="demo">  
  74.  
  75.    "cid" type="java.lang.String">  
  76.  
  77.     "sid" length="32" />  
  78.  
  79.     class="uuid.hex" />  
  80.  
  81.      
  82.  
  83.    "class"   
  84.  
  85.     class="lcx.vo.Class" 
  86.  
  87.     column="class_id"   
  88.  
  89.     not-null="true"   
  90.  
  91.    />     
  92.  
  93. class>  
  94.  
  95.  
  96.  

 

 

(一) cascade 的介紹:

當(dāng)Hibernate持久化一個(gè)“臨時(shí)對象(也叫自由態(tài)對象)”時(shí),在默認(rèn)的情況下(即:沒有設(shè)置cascade屬性或cascade=none時(shí)),Hibernate不會自動“持久化他所關(guān)聯(lián)”的其他臨時(shí)對象。

上面這些話是什么意思呢? 什么叫不會自動 “持久化”關(guān)聯(lián)的臨時(shí)對象呢?

看如下代碼:

 

  1. // 創(chuàng)建一個(gè) 臨時(shí)對象(也叫自由態(tài)對象)   
  2.  
  3. // 也就是說這個(gè) class 沒有被Hibernate納入Session緩存管理。  
  4.  
  5. Class class = new Class();  
  6.  
  7. //class.id 為自動生成  
  8.  
  9. class.setName("一年級1班");  
  10.  
  11. Student stu = new Student();  
  12.  
  13. //student.id 為自動生成  
  14.  
  15. stu.setName("小白兔");  
  16.  
  17. stu.setClass(class);  
  18.  
  19. // 關(guān)鍵就是這里。。。  
  20.  
  21. class.getStudents().add(stu);  
  22.  
  23. session.save(class);  
  24.  
  25. // 提交  
  26.  
  27. // 注意: Class.hbm.xml文件中,cascade="save-update"并且也沒有設(shè)置inverse屬性,也就是說inverse=false;  
  28.  
  29. // 此時(shí)如果你開啟了Hibernate的顯示HQL語句功能,那么控制臺將會顯示如下3條HQL:  
  30.  
  31. //----------------------------------------********  
  32.  
  33. insert into demo.class (cid, cname) values (66666666666666666666666666666666, 一年級1班)  
  34.  
  35. insert into demo.student (sid,sname,class_id) values (8888888888888888811cb2e04c888888, 小白兔, 66666666666666666666666666666666)  
  36.  
  37. update demo.student set class_id=66666666666666666666666666666666 where sid=8888888888888888811cb2e04c888888  
  38.  
  39. //----------------------------------------********  
  40.  

 

那么為什么會出現(xiàn),這3條HQL語句呢,我們來一一分析一下:

第1條HQL語句:

其實(shí)第一條HQL比較好理解,

當(dāng)我們調(diào)用 session.save(class) 后,在Hibernate進(jìn)行提交的時(shí)候,

會發(fā)現(xiàn)“有”一條“新”的數(shù)據(jù)要插入(insert),所以就往class表中,插入了這條新的class記錄。

第2條HQL語句:

注意問題就在這里:

這里為什么又出現(xiàn)了一條insert語句呢?而且還是向student表中插入數(shù)據(jù)。

我們在上面的代碼中,并沒有編寫類似“session.save(student)”這樣的語句啊。

這是為什么呢?

其實(shí)原因,是這么回事:因?yàn)槲覀冊赾lass端,設(shè)置了"級聯(lián)更新"(即:cascade="save-update"),

也就是說,當(dāng)Hibernate在向class表中插入“新”對象記錄時(shí),會檢查“Class對象”所關(guān)聯(lián)的屬性(就是對應(yīng)的屬性),是否發(fā)生過變化,如果發(fā)生了變化,就按照“級聯(lián)屬性(cascade)”所設(shè)定的內(nèi)容

進(jìn)行操作。

上面講的這句話到底是什么意思呢?

用你們“人”話說,就是:

因?yàn)檎{(diào)用了 class.getStudents().add(stu);

所以,在Hibernate在進(jìn)行插入 class對象的時(shí)候,發(fā)現(xiàn)class對象,所關(guān)聯(lián)的集合中,有一條

“自由態(tài)”的對象,而又因?yàn)閏lass端設(shè)置了“級聯(lián)屬性cascade”,所以,在插入這條 “新class對象”時(shí),也一同把他內(nèi)部的那些,還屬于“自由態(tài)”的其他對象,也一同插入到,他們所對應(yīng)的表中去了。

還是不明白的話。。。可以看看。孫衛(wèi)琴的《精通Hibernate》,在書上的第149頁有。

但是關(guān)于inverse的介紹。。。寫的就有些書面化了,如果語文不好的話。。。就難懂咯~

第3條HQL語句:

第三條HQL語句是一條update語句,是不是覺得,很莫名其妙。。。。

Hibernate大腦進(jìn)水了吧,怎么吃飽了撐得,重復(fù)更新記錄啊啊啊啊啊

假如:我們把 class端的配置文檔中的 invser屬性設(shè)置為true(即:inverse=true)

在執(zhí)行上面的程序,發(fā)現(xiàn),就變成2條insert語句啦。。。。。(update沒啦。。。)

看來第三條的update語句和inverse有著密切的關(guān)系(他兩有一腿~)。

所以我們下邊,就來介紹一下inverse屬性:

當(dāng)調(diào)用 Class.getStudents().add(stu)方法,進(jìn)行添加操作時(shí),

(即:向 "這個(gè)Class對象"所屬的“集合 (也就是調(diào)用getStudents方法所返回的那個(gè)Set集合)”中添加一個(gè)Student(即 add(stu)),也就是說,這個(gè)“新”添加的Student對象(stu),

他的Student.class_id字段“必須”,要等于“被添加方Class”的主鍵(即:Class.cid)。

從“數(shù)據(jù)庫”層面來講,也就是說,這個(gè)“新”添加的“Student”的class_id字段,必須要與“Class”的cid字段,存在"主外鍵關(guān)聯(lián)"。)

正因?yàn)槿绱耍核訦ibernate“怕” 在進(jìn)行 "Class.getStudents().add(stu)" 這樣的操作時(shí),

出現(xiàn)意外情況(如: stu.getClass=null,即:stu沒有所屬班級),

即“添加方”(Student)與“被添加方”(Class),存在“外鍵”不一致的情況發(fā)生。

所以就出現(xiàn)了 那條多余的update語句。即:one-to-many(Class端)主動去維護(hù)Child.Class_id

所以就是說,Hibernate怕出錯,就給你多執(zhí)行一次無用的更新語句,以保證 add 到 Class“集合”中的所有Student

都是要與Class有外鍵關(guān)聯(lián)的。

用普通話說就是:

一年1班.getStudents().add(小白兔);

一年1班.getStudents().add(大白兔);

也就是說現(xiàn)在不管是 小白兔 還是 大白兔

如果他們,目前還沒有自己的班級的話,

一年1班的班主任就會主動邀請他們成為一年1班的同學(xué)啦~。

也就是說 一年1班的班主任 主動邀請 同學(xué),而不是 同學(xué)自己來~~~ 所以效率也降低了。。。。

所以我們一般把 一對多端 invser設(shè)置為true,即:不讓主控端去維護(hù)主鍵關(guān)聯(lián),

(即:讓同學(xué)自己去找班級)

說白了,就是,one-to-many端不用去管理 “新添加對象” 的主外鍵約束問題。

把one-to-many端(即:class端)的invser設(shè)置為true

(即:每次向class.getStudents這個(gè)集合中添加 student時(shí),不去主動update對應(yīng)的外鍵),

而是在student端去手動設(shè)置

例如:

 

  1. student.setClass(class);  
  2.  
  3. session.save(student);  
  4.  
  5. 這樣手動設(shè)置 student與class關(guān)聯(lián)啦。。。。  
  6.  
  7. 所以上面的程序“最好”還是寫成這樣:  
  8.  
  9. Class class = new Class();  
  10.  
  11. class.setName("一年級1班");  
  12.  
  13. session.save(class);  
  14.  
  15. Student stu = new Student();  
  16.  
  17. stu.setName("小白兔");  
  18.  
  19. stu.setClass(class);  
  20.  
  21. session.save(class);  
  22.  
  23. /*  
  24.  

 

此時(shí)向class集合add內(nèi)容,不會進(jìn)行數(shù)據(jù)庫操作(update)。

“更新”的只是session緩存中,數(shù)據(jù)鏡像。

這樣做的好處是:不僅減少了update語句,

而且,同時(shí)也更新了session緩存。

------------------------

而在原來:

one-to-many端inverse=false時(shí),雖然也更新seesion緩存中的class集合,

但是有卻又多余update

 

  1. */  
  2.  
  3. class.getStudents().add(stu);  
  4.  
  5. // 提交  

 

總結(jié):

當(dāng)inverse=false 并且向one-to-many端的關(guān)聯(lián)集合,添加“新對象(即: 自由態(tài)對象)” 時(shí),

Hibernate就會自動,去update那“個(gè)剛剛到來的” “自由態(tài)對象”的外鍵。

(如果你向,one-to-many端添的集合中,add一個(gè)“已經(jīng)持久化了的對象”,那就不會出現(xiàn)update了(因?yàn)橐呀?jīng)持久化過了),除非,你去 更改“那個(gè)持久化對象”所對應(yīng)的外鍵。。。那樣的話。。。呵呵呵~~~

你可以試一試,應(yīng)該不會報(bào)錯,你可以當(dāng)做練習(xí)去做一下,加深cascade和inverse這兩個(gè)屬性的理解)

// 如果看懂了上面的內(nèi)容。來看一下,下面的東西。

假如,將one-to-many端(即:Class端)的 hbm.xml 文檔中的cascade移除掉 或把cascade="none"。

那么上面的代碼會出現(xiàn)什么情況呢。

結(jié)果會出現(xiàn)2條HQL,和一堆Exception

 

  1. insert into demo.class (cid, cname) values (66666666666666666666666666666666, 一年級1班)  
  2.  
  3. update demo.student set class_id=66666666666666666666666666666666 where sid=8888888888888888811cb2e04c888888  
  4.  
  5. Hibernate Exceptinon......................................   
  6.  

 

相比較cascade被設(shè)置"save-update"的時(shí)候,缺少了1條 insert語句,而且也多了一些Exception。

那么,到底是少了哪1條insert語句呢?

就是這條:

 

  1. insert into demo.student (sid,sname,class_id) values (8888888888888888811cb2e04c888888, 小白兔, 66666666666666666666666666666666)  
  2.  

之所以會出現(xiàn),這樣的現(xiàn)象,想必您已經(jīng)早就看出來了。

因?yàn)椋覜]有設(shè)置Class端的Cascade,所以在save(class)的時(shí)候,并沒有自動將其所關(guān)聯(lián)的“自由態(tài)對象”進(jìn)行持久化操作。

然而,又因?yàn)?Class端的inverse=false,所以,Class會自動去維持,那個(gè) “新來的student” 的外鍵。

所以會出現(xiàn),沒有insert就要update啦。。。。

然后在就是Exception了

【編輯推薦】

  1. Hibernate批量更新與刪除實(shí)例淺析
  2. 簡述Hibernate Synchronizer學(xué)習(xí)筆記
  3. Hibernate column屬性簡介
  4. 概括Hibernate查詢語言
  5. Hibernate cartridge學(xué)習(xí)總結(jié)
責(zé)任編輯:金賀 來源: ITEYE博客
相關(guān)推薦

2012-02-03 10:21:47

HibernateJava

2009-09-22 09:40:03

cascade和invHibernate

2009-06-12 14:52:21

cascadeinverseHibernate

2009-09-23 08:56:18

Hibernate cHibernate i

2009-06-18 10:29:24

Hibernate I

2009-06-12 15:05:03

cascadeHibernate

2009-07-09 16:01:27

2009-09-24 13:03:38

Hibernate C

2009-06-29 08:59:05

hbm的generat

2009-09-23 12:48:54

Hibernate I

2009-09-23 13:33:51

Hibernate屬性

2009-09-29 17:00:08

Hibernate c

2009-09-21 17:33:50

Hibernate基礎(chǔ)

2009-09-24 17:24:20

Hibernate S

2009-07-02 09:34:05

hibernate的l

2009-09-28 09:56:53

Hibernate屬性

2009-09-25 13:39:40

Hibernate屬性

2010-09-07 16:46:59

CSSexpression

2009-09-24 15:53:00

Hibernate J

2009-09-27 13:57:19

Hibernate樹形
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號