舉個例子你就能知道了!
A表(a1,b1,c1) B表(a2,b2)
a1 b1 c1 a2 b2
01 數學 95 01 張三
02 語文 90 02 李四
03 英語 80 04 王五
select A.*,B.* from A inner join B on(A.a1=B.a2)
結果是:
a1 b1 c1 a2 b2
01 數學 95 01 張三
02 語文 90 02 李四
select A.*,B.* from A left outer join B on(A.a1=B.a2)
結果是:
a1 b1 c1 a2 b2
01 數學 95 01 張三
02 語文 90 02 李四
03 英語 80 NULL NULL
select A.*,B.* from A right outer join B on(A.a1=B.a2)
結果是:
a1 b1 c1 a2 b2
01 數學 95 01 張三
02 語文 90 02 李四
NULL NULL NULL 04 王五
select A.*,B.* from A full outer join B on(A.a1=B.a2)
結果是:
a1 b1 c1 a2 b2
01 數學 95 01 張三
02 語文 90 02 李四
03 英語 80 NULL NULL
NULL NULL NULL 04 王五
4.2. 級聯(cascade)屬性的作用:
4.2.1 只有“關係標記”纔有cascade屬性:many-to-one,one-to-one ,any,
set(map, bag, idbag, list, array) + one-to-many(many-to-many)
4.2.2 級聯指的是當主控方執行操作時,關聯對象(被動方)是否同步執行同一操作。
pojo和它的關係屬性的關係就是“主控方 -- 被動方”的關係,如果關係屬性是一個set,那麼被動方就是set中的一個一個元素,。
比如:學校(School)有三個屬性:地區(Address),校長(TheMaster)和學生(Set, 元素爲Student)
執行session.delete(school)時,級聯決定是否執行session.delete(Address),session.delete(theMaster),
是否對每個aStudent執行session.delete(aStudent)。
extend:這點和inverse屬性是有區別的。見4.3.
4.2.3 一個操作因級聯cascade可能觸發多個關聯操作。前一個操作叫“主控操作”,後一個操作叫“關聯操作”。
cascade屬性的可選值:
all : 所有情況下均進行關聯操作。
none:所有情況下均不進行關聯操作。這是默認值。
save-update:在執行save/update/saveOrUpdate時進行關聯操作。
delete:在執行delete時進行關聯操作。
具體執行什麼“關聯操作”是根據“主控操作”來的:
“主控操作” “關聯操作”
session.saveOrUpdate --> session.saveOrUpdate (執行saveOrUpdate實際上會執行save或者update)
session.save ----> session.saveOrUpdate
session.udpate --> session.saveOrUpdate
session.delete --> session.delete
4.2.4 主控操作和關聯操作的先後順序是“先保存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);
}
saveOrUpdate與update的區別是:前者根據操作對象是保存了還是沒有保存,而決定執行update還是save
extends: 實際中,刪除學校不會刪除地區,即地區的cascade一般設爲false
另外,many-to-many關係很少設置cascade=true,而是設置inverse=false。這個反映了cascade和inverse的區別。見4.3
4.2.6 cascade的默認值爲false,所以inverse屬性默認會進行“關聯更新”。
4.2.7 總結:級聯(cascade)就是操作一個對象時,對它的屬性(其cascade=true)也進行這個操作。
【cseu】:
4.3 inverse和cascade的比較
這兩個屬性本身互不影響,但起的作用有些類似,都能引發對關係表的更新。4.3.1 inverse只對set+one-to-many(或many-to-many)有效,對many-to-one, one-to-one無效。
cascade對關係標記都有效。4.3.2 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會判斷操作的對象是否改變)
4.3.2 兩個起作用的時機不同:
cascade:在對主控方操作時,級聯發生。inverse: 在flush時(commit會自動執行flush),對session中的所有set,hibernate判斷每個set是否有變化,
對有變化的set執行相應的sql,執行之前,會有個判斷:if( inverse == true ) return;
可以看出cascade在先,inverse在後。
4.3.3 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
方的數據庫表。
4.3.4 建議:只對set + many-to-many設置inverse=false,其他的標記不考慮inverse屬性,都設爲inverse=true。
對cascade,一般對many-to-one,many-to-many,constrained=true的one-to-one 不設置級聯刪除。