Hibernate中的cascade和inverse

這兩個屬性都用於一多對或者多對多的關係中。而inverse特別是用於雙向關係,在單向關係中咱們並不須要。 java

 

Cascade表明是否執行級聯操做,Inverse表明是否由己方維護關係。 spring

 

Cascade: 數據庫

 

Cascade屬性的可能值有 this

    all: 全部狀況下均進行關聯操做,即save-update和delete。
    none: 全部狀況下均不進行關聯操做。這是默認值。
    save-update: 在執行save/update/saveOrUpdate時進行關聯操做。
    delete: 在執行delete 時進行關聯操做。 spa

    all-delete-orphan: 當一個節點在對象圖中成爲孤兒節點時,刪除該節點。好比在一個一對多的關係中,Student包含多個book,當在對象關係中刪除一個book時,此book即成爲孤兒節點。 hibernate

 

Inverse: code

 

Inverse屬性的可能值是true或者false,默認爲false: xml

 

     false表明由己方來維護關係,true表明由對方來維護關係。在一個關係中,只能由一方來維護關係,不然會出問題(解疑中會講到);同時也必須由一方來維護關係,不然會出現雙方互相推卸責任,誰也無論。 對象

 

一多對的例子: ip

 

有兩個類,Father和Child,是一對多的關係。下面這段hbm配置是從Father.hbm.xml中摘取的。

 

 

<set name="children" lazy="true" cascade="all" inverse="true">
    <key column="fatherid"/>
    <one-to-many class="my.home.Child"/>
</set>

 

咱們知道cascade和inverse的值對會有四種組合的可能(在此僅先假定cascade值爲none或all)。

 

有以下一段代碼:

 

Java代碼   收藏代碼
  1. FatherDao fatherDao = new FatherDao();  
  2.   
  3. Father father = new Father("David");  
  4. Child child1 = new Child("David Junior One");  
  5. Child child2 = new Child("David Junior Two");  
  6.   
  7. father.add(child1);  
  8. father.add(child2);  
  9.   
  10. fatherDao.save(father);  

 

1. 若是cascade="all"且inverse="false"時:

 

此時能夠看到log裏面:

 

Java代碼   收藏代碼
  1. // 執行對father的插入  
  2. Hibernate: insert into father (name) values (?)  
  3.   
  4. // cascade = 'all',因此進行級聯操做  
  5. Hibernate: insert into child (name, fatherid) values (?, ?)  
  6. Hibernate: insert into child (name, fatherid) values (?, ?)  
  7.   
  8. // inverse = 'false',由father來維護關係(能夠看到這些操做是多餘的)  
  9. Hibernate: update child set fatherid =? where ID=?  
  10. Hibernate: update child set fatherid =? where ID=?  
 

2. 若是cascade = "none" 且 inverse = "false":

 

Java代碼   收藏代碼
  1. // 執行對father的插入  
  2. Hibernate: insert into father (name) values (?)  
  3.   
  4. // inverse='false',因此更新關係  
  5. Hibernate: update child set fatherid =? where ID=?  
  6.   
  7. // 但因爲cascade='none',child並未插入數據庫,致使以下exception  
  8. org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance  
 

3. 若是cascade = "all" 且 inverse = "true"

 

Java代碼   收藏代碼
  1. // 執行對father的插入  
  2. Hibernate: insert into father (name) values (?)  
  3.   
  4. // cascade='all',執行對child的插入  
  5. Hibernate: insert into child (name, fatherid) values (?, ?)  
  6. Hibernate: insert into child (name, fatherid) values (?, ?)  
  7.   
  8. // 但因爲inverse='true',因此未有對關係的維護。但因爲一對多的關係中,關係自己在「多」方的表中。因此,無需更新  
  9. 關係。  
 

4. 若是cascade = "none" 且 inverse = "true"

 

Java代碼   收藏代碼
  1. // 只執行對father的插入  
  2. Hibernate: insert into father (name) values (?)  
 

能夠看到,對於一對多關係,關係應由「多」方來維護(指定「一」方的inverse爲true),而且應在「一」方指定相應的級聯操做。

 

多對多:

 

在多對多關係中,inverse能夠爲任何一方,沒有什麼區別。

 

解疑:

 

爲何在多對多中不能由雙方都來維護關係了:由於這樣會致使重複更新中間表的可能,報出重複值的錯誤。

 

那麼如何在多對多的雙向關聯中使雙方都能維護關係:最好讓控制關係的那方來更新關係,若是想讓另外一方也來維護關係,那麼只有在操做這一方的數據時「顯式」更新中間表了吧。

 

注意:

 

同時注意在雙向關聯中,對象之間的關聯跟上面說起的關係表維護沒有關係。一個是對象/java層面的,一個是hibernate數據庫層面的。若是你想在更新一方時,也更新另外一方的對象集合,請看下面這段代碼:

 

這是Person類中的一段代碼,Person和Event是多對多的雙向關聯關係,他們在對方類中的集合分別爲participants和events。關係表由Person維護,因此對象關係的維護也在Person類中,而不是Event類中。

 

Java代碼   收藏代碼
  1. public void addToEvent(Event event) {  
  2.         this.getEvents().add(event);  
  3.         event.getParticipants().add(this);  
  4. }  
  5.   
  6. public void removeFromEvent(Event event) {  
  7.         this.getEvents().remove(event);  
  8.         event.getParticipants().remove(this);  
  9. }  
 
相關文章
相關標籤/搜索