Hibernate中cascade做用

    只有「關係標記」纔有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

相關文章
相關標籤/搜索