只有「關係標記」纔有cascade屬性;
一個操做因級聯cascade可能觸發多個關聯操做。前一個操做叫「主控操做」,後一個操做叫「關聯操做」。
cascade屬性的可能值有
all: 全部狀況下均進行關聯操做,即save-update和delete。
none: 全部狀況下均不進行關聯操做。這是默認值。
save-update: 在執行save/update/saveOrUpdate時進行關聯操做。
delete: 在執行delete 時進行關聯操做。
all-delete-orphan: 當一個節點在對象圖中成爲孤兒節點時,刪除該節點。好比在一個一對多的關係中,Student包含多個book,當在對象關係中刪除一個book時,此book即成爲孤兒節點。
級聯(cascade)屬性的做用:
級聯指的是當主控方執行操做時,關聯對象(被動方)是否同步執行同一操做。
pojo和它的關係屬性的關係就是「主控方 -- 被動方」的關係,若是關係屬性是一個set,那麼被動方就是set中的一個一個元素。
好比:學校(School)有三個屬性:地區(Address),校長(TheMaster)和學生(Set,元素爲Student)
執行session.delete(school)時,級聯決定是否執行session.delete(Address),session.delete(theMaster),
是否對每一個aStudent執行session.delete(aStudent)。
具體執行什麼「關聯操做」是根據「主控操做」來的:
「主控操做」 「關聯操做」
session.saveOrUpdate --> session.saveOrUpdate (執行saveOrUpdate實際上會執行save或者update)
session.save ----> session.saveOrUpdate
session.udpate --> session.saveOrUpdate
session.delete --> session.delete
主控操做和關聯操做的前後順序是「先保存one,再保存many;先刪除many,再刪除one;先update主控方,再update被動方」
對於one-to-one,當其屬性constrained="false"(默認值)時,它可看做one-to-many關係;
當其屬性constrained="true"時,它可看做many-to-one關係;
對many-to-many,它可看做one-to-many。
好比:學校(School)有三個屬性:地區(Address),校長(TheMaster,其constrained="false")和學生(Set, 元素爲Student)
當執行session.save(school)時,
實際的執行順序爲:session.save(Address);
session.save(school);
session.save(theMaster);
for( 對每個student ){
session.save(aStudent);
}
當執行session.delete(school)時,
實際的執行順序爲:session.delete(theMaster);
for( 對每個student ){
session.delete(aStudent);
}
session.delete(school);
session.delete(Address);
當執行session.update(school)時,
實際的執行順序爲:session.update(school);
session.saveOrUpdate(Address);
session.saveOrUpdate(theMaster);
for( 對每個student ){
session.saveOrUpdate(aStudent);
}
注意:update操做因級聯引起的關聯操做爲saveOrUpdate操做,而不是update操做。
saveOrUpdate與update的區別是:前者根據操做對象是保存了仍是沒有保存,而決定執行update仍是save
extends: 實際中,刪除學校不會刪除地區,即地區的cascade通常設爲false;另外,many-to-many關係不多設置cascade=true,而是設置inverse=false。這個反映了cascade和inverse的區別。
cascade的默認值爲false,因此inverse屬性默認會進行「關聯更新」。
總結:級聯(cascade)就是操做一個對象時,對它的屬性(其cascade=true)也進行這個操做。
inverse和cascade的比較
這兩個屬性自己互不影響,但起的做用有些相似,都能引起對關係表的更新。
inverse只對set+one-to-many(或many-to-many)有效,對many-to-one, one-to-one無效。
cascade對關係標記都有效。
inverse對集合對象總體起做用,cascade對集合對象中的一個一個元素起做用,若是集合爲空,那麼cascade不會引起關聯操做。
好比將集合對象置爲null, school.setStudentSet(null)
inverse致使hibernate執行:udpate STUDENT set SCHOOL_ID=null where SCHOOL_ID=?
cascade則不會執行對STUDENT表的關聯更新, 由於集合中沒有元素。
再比新增一個school, session.save(school)
inverse致使hibernate執行:
for( 對(school的每個student ){
udpate STUDENT set SCHOOL_ID=? where STUDENT_ID=? //將學生的school_id改成新的school的id
}
cascade致使hibernate執行:
for( 對school的每個student ){
session.save(aStudent); //對學生執行save操做
}
extends:若是改變集合中的部分元素(好比新增一個元素),
inverse: hibernate先判斷哪些元素改變了,對改變的元素執行相應的sql
cascade: 它老是對集合中的每一個元素執行關聯操做。
(在關聯操做中,hibernate會判斷操做的對象是否改變)
兩個起做用的時機不一樣:
cascade:在對主控方操做時,級聯發生。
inverse: 在flush時(commit會自動執行flush),對session中的全部set,hibernate判斷每一個set是否有變化,對有變化的set執行相應的sql,執行以前,會有個判斷:if( inverse == true ) return;能夠看出cascade在先,inverse在後。
inverse 對set + one-to-many 和 set + many-to-many 起的做用不一樣。hibernate生成的sql不一樣。
對one-to-many,hibernate對many方的數據庫表執行update語句。
對many-to-many, hibernate對關係表執行insert/update/delte語句,注意不是對many方的數據庫表而是關係表。
cascase 對set都是一致的,無論one-to-many仍是many-to-many。都簡單地把操做傳遞到set中的每一個元素。因此它老是更新many方的數據庫表。
建議:只對set + many-to-many設置inverse=false,其餘的標記不考慮inverse屬性,都設爲inverse=true。
對cascade,通常對many-to-one,many-to-many,constrained=true的one-to-one 不設置級聯刪除。web