hibernate裡inverse和cascade的理解
首先,來看inverse和cacade的取值有哪些..
1. cascade 有五個選項 分別是: all ,delete ,none,save-update,delete-orphan ;
2. inverse 有兩個值 true ,false
這幾個值各是什麼呢?
cascade的五個值:
all:所有情況下均進行關聯操作,即save-update + delete.
none:所有情況下均不進行關聯操作。這是預設值。
save-update:在執行save/update/saveOrUpdate時進行關聯操作。
delete:在執行delete時進行關聯操作。
delete-orphan: 當save/update/saveOrUpdate時,相當於save-update;刪除時,相當於delete
還有個 all-delete-orphan :是當物件圖中產生孤兒節點時,在資料庫中刪除該節點 。//不太明白
inverse:ture 表示主控權交給關聯類來執行
false預設值 ,由自己來行駛主控權
inverse屬性預設是false的,就是說關係的兩端都來維護關係。這個意思就是說,如有一個Student, Teacher和TeacherStudent表,Student和Teacher是多對多對多關係,這個關係由TeacherStudent這個表來表 現。那麼什麼時候插入或刪除TeacherStudent表中的記錄來維護關係呢?在用hibernate時,我們不會顯示的對 TeacherStudent表做操作。對TeacherStudent的操作是hibernate幫我們做的。hibernate就是看hbm檔案中指 定的是"誰"維護關係,那個在插入或刪除"誰"時,就會處發對關係表的操作。前提是"誰"這個物件已經知道這個關係了,就是說關係另一頭的物件已經set 或是add到"誰"這個物件裡來了。前面說過inverse預設是false,就是關係的兩端都維護關係,對其中任一個操作都會處發對錶系表的操作。當在關係的一頭,如Student中的bag或set中用了inverse="true"時,那就代表關係是由另一關維護的(Teacher)。就是說當這插入Student時,不會操作TeacherStudent表,即使Student已經知道了關係。只有當Teacher插入或刪除時才會處發對關係表的操作。所以,當關系的兩頭都用inverse="true"是不對的,就會導致任何操作都不處發對關係表的操作。當兩端都是inverse= "false"或是default值是,在程式碼對關係顯示的維護也是不對的,會導致在關係表中插入兩次關係。
在一對多關係中inverse就更有意義了。在多對多中,在哪端inverse="true"效果差不多(在效率上)。但是在一對多中,如果要一方維護關係,就會使在插入或是刪除"一"方時去update"多"方的每一個與這個"一"的物件有關係的物件(注意:這裡所指的有關係一般是指的設定多方的ID屬性,使之與一方的關聯在一起)。而如果讓"多"方面維護關係時就不會有update 操作,因為關係就是在多方的物件中的,直指插入或是刪除多方物件就行了。當然這時也要遍歷"多"方的每一個物件顯示的操作修關係的變化體現到DB中。不管
怎樣說,還是讓"多"方維護關係更直觀一些。
(1)對one-to-many而言,改變set,會讓hibernate執行一系列的update語句,不會delete/insert資料
(2)對many-to-many而言,改變set,只修改關係表的資料,不會影響many-to-many的另一方。
(3)雖然one-to-many和many-to-many的資料庫操作不一樣,但目的都是一個:維護資料的一致性。
測試:
一對多關係的兩張表:boy、girl(一個男孩可以多個女朋友)
boy表結構
Field Type
------ -----------
name varchar(50) pk
age varchar(50)
girl表結構
Field Type
------ -----------
name varchar(50) pk
bf varchar(50) fk
【儲存時:Inverse與cascade】
建立三個girl物件和一個boy物件,讓這是三個girl都是boy的女朋友
---------建立物件的程式碼片段-----------
Boy boy = new Boy("tom","23", null);
Set girls = new HashSet();
Girl g[] = new Girl[]{
new Girl("Alice1", boy),
new Girl("Alice2", boy),
new Girl("Alice3", boy)
};
girls.add(g[0]);
girls.add(g[1]);
girls.add(g[2]);
boy.setGirls(girls);
session.save(boy);
在Boy.hbm.xml中設定,
1.Inverse = true,不指定cascade 既為none
cascade的預設值為none, 當對boy進行儲存操作時,girl什麼都不做. 所以只儲存了boy物件, 沒有儲存girl物件
2.Inverse = true,cascade=all (由多方來維護關係,那麼不需要update,因為它關係就在它那兒)
boy與girl物件,包擴外來鍵都成功儲存。只不過girl表中的對應的id是null
(SELECT 3, INSERT 4)
3.Inverse = false,不指定cascade,既為none
報錯。因為boy為主控方,負責維護關係,在維護關係是發現並不存在girl記錄,所以不能建立關係。
4.Inverse = false,cascade=all (由一方維護關係,那麼會產生update)
boy與girl物件,包擴外來鍵都成功儲存。
(SELECT 3, INSERT 4, UPDATE 3)
分析:除了4條INSERT語句之外,其他的6條語句是我們為了圖方便付出的代價:3條SELECT語句用來判斷girl物件是否在資料表中已經存在,3條UPDATE語句是為了維護外來鍵關係
高效率的做法:在Boy.hbm.xml中設定Inverse=true,在Girl.hbm.xml中設定cascade=all,然後儲存三個girl物件
(SELECT 1, INSERT 4)
高效率的代價就是儲存的時候比較麻煩
【刪除時:Inverse與cascade】
希望通過刪除boy,也將3個girl物件刪除。程式中先查出boy物件,然後進行刪除
-----------------------------------------
Boy boy = (Boy) s.get(Boy.class, "tom");
s.delete(boy);
-----------------------------------------
同樣在Boy.hbm.xml中進行設定
1.Inverse = true cascade = none
可以猜到結果是出錯。原因:外來鍵約束錯誤,他沒有維護關係,所以引起外間衝突
2.Inverse = false cascade = none
boy刪除,girl表中外來鍵變為null,沒有刪除記錄 ;
(UPDATE 1, DELETE 1)
3.Inverse = false, cascade = all
全部刪除 ;在刪除有外來鍵的從表時,先把從表外來鍵置為null,然後刪除主表記錄,最後根據從表主鍵刪除所有相關從表記錄
(UPDATE 1, DELETE 4)
4.Inverse = true, cascade = all
全部刪除
(DELETE 4)
Inverse是hibernate雙向關係中的基本概念,當然對於多數實體,我們並不需要雙向關聯,更多的可能會選擇單向關聯,況且我們大多數人一般採用一對多關係,而一對多雙向關聯的另一端:多對一的inverse屬性是不存在,其實它預設就是inverse=false.從而防止了在一對多端胡亂設定inverse也不至於出錯。但是inverse設定不當確實會帶來很大的效能影響,這點是我們必須關注的。
看了這篇文章,還是很有必要再寫下一些總結的:
1)inverse中提及的side其實是指一個類或者表的概念,雙向關聯其實是指雙方都可以取得對方的應用。
2)維護關係這個名詞還是稍顯模糊或者晦澀。我們一般說A類或者A表(這裡的表的是指多對多的連線表)有責任維護關係,其實這裡的意思是說,我在應用在更新,建立,刪除(讀就不用說了,雙向引用正是為了方便讀而出現)A類或者A表時,此時建立的SQL語句必須有責任保證關係的正確修改。
3)inverse=false的side(side其實是指inverse=false所位於的class元素)端有責任維護關係,而inverse=true端無須維護這些關係。
4)我們說inverse設立不當會導致效能低下,其實是說inverse設立不當,會產生多餘重複的SQL語句甚至致使JDBC exception的throw。這是我們在建立實體類關係時必須需要關注的地方。一般來說,inverse=true是推薦使用,雙向關聯中雙方都設定 inverse=false的話,必會導致雙方都重複更新同一個關係。但是如果雙方都設立inverse=true的話,雙方都不維護關係的更新,這也是不行的,好在一對多中的一端:many-to-one預設是inverse=false,避免了這種錯誤的產生。但是對多對就沒有這個預設設定了,所以很多人經常在多對多的兩端都使用inverse=true,結果導致連線表的資料根本沒有記錄,就是因為他們雙方都沒有責任維護關係。所以說,雙向關聯中最好的設定是一端為inverse=true,一端為inverse=false。一般inverse=false會放在多的一端,那麼有人提問了,
many-to-many兩邊都是多的,inverse到底放在哪兒?其實hibernate建立多對多關係也是將他們分離成兩個一對多關係,中間連線一個連線表。所以通用存在一對多的關係,也可以這樣說:一對多是多對多的基本組成部分。
相關文章
- Hibernate【inverse和cascade屬性】知識要點
- hibernate(六) cascade(級聯)和inverse關係詳解
- 正確理解Hibernate Inverse (轉)
- Hibernate的cascade總結
- hibernate裡createSQLQuery的addEntity()和setResultTransformer()方法SQLORM
- MyBatis和Hibernate相比,優勢在哪裡?MyBatis
- inverse of arc length
- Hibernate 框架理解框架
- Hibernate flush理解
- 暈,hibernate 的 merge和cascade="all-delete-orphan"要慎重合在一起使用delete
- 理解 Ruby 裡的 blockBloC
- 我理解的Persistent Object Identity in HibernateObjectIDE
- Java Web之理解 Hibernate And MyBatisJavaWebMyBatis
- 同是ZooKeeper,你和架構師的理解差在哪裡?架構
- Oracle中drop user和drop user cascade的區別Oracle
- 深入理解hibernate的三種狀態
- Hibernate中flush機制的詳細理解
- hibernate 能用在app cluster裡面嗎?APP
- js裡的物件基本理解(原型)JS物件原型
- 如何理解ASM裡FAILGROUP的概念ASMAI
- Cascade屬性
- ORACLE CASCADE DATAGUARDOracle
- 如果一個應用裡同時存在EntityBean和Hibernate怎麼辦Bean
- exths 裡的 Ext.getEl()的理解
- HIBERNATE的SESSION和事務Session
- Hibernate分頁查詢原理解讀
- hibernate案例裡的那個HibernateTemplateTest怎麼執行
- Oracle中"cascade"的用法總結Oracle
- D. Matrix Cascade
- FLEX和spring、hibernate的整合FlexSpring
- hibernate list和iterate
- hibernate中建立session的兩種方式方式,區別在哪裡?Session
- 概述.NET裡對 remoting 和 webservice 兩項技術的理解和實際中的應用REMWeb
- 關於delete cascade的小實驗delete
- hibernate原始碼和jar的下載原始碼JAR
- HIBERNATE裡面怎麼繼承一對多的關係呢繼承
- 主外來鍵關聯刪除(on delete set null和on delete cascade)deleteNull
- Drop table cascade constraintsAI