国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Hibernate中cascade與inverse屬性詳解
(原創(chuàng)) Hibernate中cascade與inverse屬性詳解

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

您買(mǎi)的Hibernate書(shū)是哪一本呢? 孫衛(wèi)琴的精通Hibernate,還是 深入淺出Hibernate還是那本。。。
我是兩本都買(mǎi)了,總體來(lái)說(shuō)還可以,但是,有的地方講的比較書(shū)面化,比如inverse這屬性。

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

據(jù)個(gè)例子:書(shū)上說(shuō)inverse=false時(shí),由主控方維持關(guān)系。。。
由于我也是初學(xué)者。。。再加上語(yǔ)文水平偏低。。。不理解“維持關(guān)系是啥意思”囧~

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

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

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

(4)如果:您對(duì)Hibernate中Session緩存,沒(méi)有初步了解的話(huà)。
(在Hibernate中調(diào)用save進(jìn)行存儲(chǔ)數(shù)據(jù)的時(shí)候,并不是馬上就對(duì)數(shù)據(jù)庫(kù)進(jìn)行insert操作,而是會(huì)將其“數(shù)據(jù)對(duì)象(vo)”納入Hibernate的Session緩存。)

在上面的4條提示中,如果您對(duì)其中的某一條,不是很清楚的話(huà)。希望請(qǐng)先了解有關(guān)知識(shí)。
否則,可能您將 “無(wú)法或很難”理解 cascade 或 inverse 這2個(gè)屬性。

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

這里有兩個(gè)表:

(1)class   (班級(jí)表)
相應(yīng)字段:
cid    varchar(32) 主鍵 not-null (班級(jí)id)
cname varchar(16)      not-null (班級(jí)名稱(chēng))  

(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é)生所屬班級(jí))

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

//--------Class類(lèi)的代碼--------
public class Class implements.....
{
private cId = "";
private cName = "";
private students = java.util.HashMap();
// 省略對(duì)應(yīng)的 geter setter
}
//--------Class.hbm.xml--------
<hibernate-mapping>
<class name="lcx.vo.Class" table="class"
   catalog="demo">
   <id name="cid" type="java.lang.String">
    <column name="cid" length="32" />
    <generator class="uuid.hex" />
   </id>
   <property name="name" type="java.lang.String">
    <column name="cname" length="16" not-null="true" />
   </property>
  
   <set name="students" table="student" cascade="save-update">
    <key column="class" />
    <one-to-many class="lcx.vo.Student" />
   </set>
</class>
</hibernate-mapping>

//--------Student類(lèi)的代碼;*******
public class Student implements.....
{
private sId = "";
private sName = "";
private Class class = null;
// 省略對(duì)應(yīng)的 geter setter
}
// Student.hbm.xml
<hibernate-mapping>
<class name="lcx.vo.Student" table="student" catalog="demo">
   <id name="cid" type="java.lang.String">
    <column name="sid" length="32" />
    <generator class="uuid.hex" />
   </id>
   <many-to-one name="class"
    class="lcx.vo.Class"
    column="class_id"
    not-null="true"
   />   
</class>
</hibernate-mapping>

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

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

看如下代碼:

// 創(chuàng)建一個(gè) 臨時(shí)對(duì)象(也叫自由態(tài)對(duì)象)
// 也就是說(shuō)這個(gè) class 沒(méi)有被Hibernate納入Session緩存管理。
Class class = new Class();
//class.id 為自動(dòng)生成
class.setName("一年級(jí)1班");

Student stu = new Student();
//student.id 為自動(dòng)生成
stu.setName("小白兔");
stu.setClass(class);

// 關(guān)鍵就是這里。。。
class.getStudents().add(stu);

session.save(class);
// 提交

// 注意: Class.hbm.xml文件中,cascade="save-update"并且也沒(méi)有設(shè)置inverse屬性,也就是說(shuō)inverse=false;
// 此時(shí)如果你開(kāi)啟了Hibernate的顯示HQL語(yǔ)句功能,那么控制臺(tái)將會(huì)顯示如下3條HQL:

//----------------------------------------********
insert into demo.class (cid, cname) values (66666666666666666666666666666666, 一年級(jí)1班)
insert into demo.student (sid,sname,class_id) values (8888888888888888811cb2e04c888888, 小白兔, 66666666666666666666666666666666)
update demo.student set class_id=66666666666666666666666666666666 where sid=8888888888888888811cb2e04c888888
//----------------------------------------********

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

第1條HQL語(yǔ)句:
其實(shí)第一條HQL比較好理解,
當(dāng)我們調(diào)用 session.save(class) 后,在Hibernate進(jìn)行提交的時(shí)候,
會(huì)發(fā)現(xiàn)“有”一條“新”的數(shù)據(jù)要插入(insert),所以就往class表中,插入了這條新的class記錄。

第2條HQL語(yǔ)句:
注意問(wèn)題就在這里:
這里為什么又出現(xiàn)了一條insert語(yǔ)句呢?而且還是向student表中插入數(shù)據(jù)。
我們?cè)谏厦娴拇a中,并沒(méi)有編寫(xiě)類(lèi)似“session.save(student)”這樣的語(yǔ)句啊。
這是為什么呢?
其實(shí)原因,是這么回事:因?yàn)槲覀冊(cè)赾lass端,設(shè)置了"級(jí)聯(lián)更新"(即:cascade="save-update"),
也就是說(shuō),當(dāng)Hibernate在向class表中插入“新”對(duì)象記錄時(shí),會(huì)檢查“Class對(duì)象”所關(guān)聯(lián)的屬性(就是<set>對(duì)應(yīng)的屬性),是否發(fā)生過(guò)變化,如果發(fā)生了變化,就按照“級(jí)聯(lián)屬性(cascade)”所設(shè)定的內(nèi)容
進(jìn)行操作。

上面講的這句話(huà)到底是什么意思呢?
用你們“人”話(huà)說(shuō),就是:
因?yàn)檎{(diào)用了 class.getStudents().add(stu);
所以,在Hibernate在進(jìn)行插入 class對(duì)象的時(shí)候,發(fā)現(xiàn)class對(duì)象,所關(guān)聯(lián)的集合中,有一條
“自由態(tài)”的對(duì)象,而又因?yàn)閏lass端設(shè)置了“級(jí)聯(lián)屬性cascade”,所以,在插入這條 “新class對(duì)象”時(shí),也一同把他內(nèi)部的那些,還屬于“自由態(tài)”的其他對(duì)象,也一同插入到,他們所對(duì)應(yīng)的表中去了。

還是不明白的話(huà)。。??梢钥纯?。孫衛(wèi)琴的《精通Hibernate》,在書(shū)上的第149頁(yè)有。
但是關(guān)于inverse的介紹。。。寫(xiě)的就有些書(shū)面化了,如果語(yǔ)文不好的話(huà)。。。就難懂咯~

第3條HQL語(yǔ)句:
第三條HQL語(yǔ)句是一條update語(yǔ)句,是不是覺(jué)得,很莫名其妙。。。。
Hibernate大腦進(jìn)水了吧,怎么吃飽了撐得,重復(fù)更新記錄啊啊啊啊啊
假如:我們把 class端的配置文檔中的 invser屬性設(shè)置為true(即:inverse=true)
在執(zhí)行上面的程序,發(fā)現(xiàn),就變成2條insert語(yǔ)句啦。。。。。(update沒(méi)啦。。。)
看來(lái)第三條的update語(yǔ)句和inverse有著密切的關(guān)系(他兩有一腿~)。

所以我們下邊,就來(lái)介紹一下inverse屬性:

當(dāng)調(diào)用 Class.getStudents().add(stu)方法,進(jìn)行添加操作時(shí),
(即:向 "這個(gè)Class對(duì)象"所屬的“集合 (也就是調(diào)用getStudents方法所返回的那個(gè)Set集合)”中添加一個(gè)Student(即 add(stu)),也就是說(shuō),這個(gè)“新”添加的Student對(duì)象(stu),
他的Student.class_id字段“必須”,要等于“被添加方Class”的主鍵(即:Class.cid)。
從“數(shù)據(jù)庫(kù)”層面來(lái)講,也就是說(shuō),這個(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沒(méi)有所屬班級(jí)),
即“添加方”(Student)與“被添加方”(Class),存在“外鍵”不一致的情況發(fā)生。
所以就出現(xiàn)了 那條多余的update語(yǔ)句。即:one-to-many(Class端)主動(dòng)去維護(hù)Child.Class_id
所以就是說(shuō),Hibernate怕出錯(cuò),就給你多執(zhí)行一次無(wú)用的更新語(yǔ)句,以保證 add 到 Class“集合”中的所有Student
都是要與Class有外鍵關(guān)聯(lián)的。

用普通話(huà)說(shuō)就是:
一年1班.getStudents().add(小白兔);
一年1班.getStudents().add(大白兔);

也就是說(shuō)現(xiàn)在不管是 小白兔 還是 大白兔
如果他們,目前還沒(méi)有自己的班級(jí)的話(huà),
一年1班的班主任就會(huì)主動(dòng)邀請(qǐng)他們成為一年1班的同學(xué)啦~。

也就是說(shuō) 一年1班的班主任 主動(dòng)邀請(qǐng) 同學(xué),而不是 同學(xué)自己來(lái)~~~ 所以效率也降低了。。。。

所以我們一般把 一對(duì)多端 invser設(shè)置為true,即:不讓主控端去維護(hù)主鍵關(guān)聯(lián),
(即:讓同學(xué)自己去找班級(jí))
說(shuō)白了,就是,one-to-many端不用去管理 “新添加對(duì)象” 的主外鍵約束問(wèn)題。

把one-to-many端(即:class端)的invser設(shè)置為true
(即:每次向class.getStudents這個(gè)集合中添加 student時(shí),不去主動(dòng)update對(duì)應(yīng)的外鍵),
而是在student端去手動(dòng)設(shè)置
例如:
student.setClass(class);
session.save(student);
這樣手動(dòng)設(shè)置 student與class關(guān)聯(lián)啦。。。。
所以上面的程序“最好”還是寫(xiě)成這樣:

Class class = new Class();
class.setName("一年級(jí)1班");
session.save(class);

Student stu = new Student();
stu.setName("小白兔");
stu.setClass(class);
session.save(class);

/*
此時(shí)向class集合add內(nèi)容,不會(huì)進(jìn)行數(shù)據(jù)庫(kù)操作(update)。
“更新”的只是session緩存中,數(shù)據(jù)鏡像。
這樣做的好處是:不僅減少了update語(yǔ)句,
而且,同時(shí)也更新了session緩存。
------------------------
而在原來(lái):
one-to-many端inverse=false時(shí),雖然也更新seesion緩存中的class集合,
但是有卻又多余update
*/
class.getStudents().add(stu);
// 提交

總結(jié):
當(dāng)inverse=false 并且向one-to-many端的關(guān)聯(lián)集合,添加“新對(duì)象(即: 自由態(tài)對(duì)象)” 時(shí),
Hibernate就會(huì)自動(dòng),去update那“個(gè)剛剛到來(lái)的” “自由態(tài)對(duì)象”的外鍵。
(如果你向,one-to-many端添的集合中,add一個(gè)“已經(jīng)持久化了的對(duì)象”,那就不會(huì)出現(xiàn)update了(因?yàn)橐呀?jīng)持久化過(guò)了),除非,你去 更改“那個(gè)持久化對(duì)象”所對(duì)應(yīng)的外鍵。。。那樣的話(huà)。。。呵呵呵~~~
你可以試一試,應(yīng)該不會(huì)報(bào)錯(cuò),你可以當(dāng)做練習(xí)去做一下,加深cascade和inverse這兩個(gè)屬性的理解)


// 如果看懂了上面的內(nèi)容。來(lái)看一下,下面的東西。
假如,將one-to-many端(即:Class端)的 hbm.xml 文檔中的cascade移除掉 或把cascade="none"。
那么上面的代碼會(huì)出現(xiàn)什么情況呢。
結(jié)果會(huì)出現(xiàn)2條HQL,和一堆Exception

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

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

那么,到底是少了哪1條insert語(yǔ)句呢?
就是這條:
insert into demo.student (sid,sname,class_id) values (8888888888888888811cb2e04c888888, 小白兔, 66666666666666666666666666666666)

之所以會(huì)出現(xiàn),這樣的現(xiàn)象,想必您已經(jīng)早就看出來(lái)了。
因?yàn)?,我沒(méi)有設(shè)置Class端的Cascade,所以在save(class)的時(shí)候,并沒(méi)有自動(dòng)將其所關(guān)聯(lián)的“自由態(tài)對(duì)象”進(jìn)行持久化操作。
然而,又因?yàn)?Class端的inverse=false,所以,Class會(huì)自動(dòng)去維持,那個(gè) “新來(lái)的student” 的外鍵。
所以會(huì)出現(xiàn),沒(méi)有insert就要update啦。。。。
然后在就是Exception了

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶(hù)發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
HIBERNATE一對(duì)多配置實(shí)例
Java程序員從笨鳥(niǎo)到菜鳥(niǎo)之(五十四)細(xì)談Hibernate(五)Hibernate一對(duì)多關(guān)系映射
hibernate中cascade和inverse
Hibernate中inverse="true"的理解
hibernate中inverse的用法
hibernate inverse樣例
更多類(lèi)似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服