一對多,多對多,一對一的理解
關系維護方和被維護方的理解:關系維護方就是hibernate會主動去修改維護的,比如one1設置為關系維護方,one2為被維護方,那麽在one1.save時,會主動修改one2,但是當one2save時就不會去管one1,除非你設置one2.save(one1),
當多的一方滿足1、關系維護方和2、設置了級聯屬性。那麽在做save操作前,只需要對多的一方做設置(如order.setUser(user))就可以了,不需要一的一方做設置(即不需要user.setOrders())。所以如果是一的一方做save操作時,必須兩方都做設置(order.setUser(user)和user.setOrders())。因為在註解中,一的一方不能滿足它是關系維護方這個條件。
所以我們將一的一方是設置級聯,多的一方不設置級聯,但設置為關系維護方是不合理的,我們可以將多的一方也設置級聯,但如果將多的一方的cascade 設為 CascadeType.ALL,那麽如果刪除多的一方,會將一的一方也刪除,所以設為 cascade = {CascadeType.PERSIST,CascadeType.REFRESH}即可。
所以如果你要person刪除所有,那麽設置person為ALL,而order設置為PERSIST,這就可以實現人沒了,訂單也沒了,刪除訂單不會刪除人。
---------------------
原文:https://blog.csdn.net/u011302734/article/details/76868090
mappedBy的理解:
聲明於關系的被維護方,聲明的值為關系的維護方的關系對象屬性名。
在實例中,mappedBy被聲明於person類中,其值為Order類中的Set對象"person"。即,Order為關系維護方,person為被維護方。
級聯的理解:級聯的定義是一方操作會影響另一方。比如one1和one2進行級聯,在one1設置級聯cascade,那麽在修改one1的時候也會修改one2,比如刪除one1,設置cascade為ALL,就會刪除one2。
@OneToOne(cascade =CascadeType.ALL)
private One2 one2;
Cascade的幾種級聯操作
指定cascade = CascadeType.PERSIST
在實體類關聯的實體字段上,那麽保存該實體類時會級聯保存該實體類關聯的實體。即可以在添加one1保存時可以級聯保存one2;
cascade = CascadeType.All
,執行所有操作,包含PERSIST,即可以在添加one1保存時可以級聯保存one2,級聯刪除時也可以刪除one1,並且順帶刪除one2;
cascade = CascadeType.REMOVE,
級聯刪除,但是必須one1和one2在數據庫中都有,才可以級聯刪除,測試的時候,你要new one1,還要new one2,然後保存one1,one2到數據庫才可以進行級聯刪除。
cascade = CascadeType.MERGE
CascadeType.MERGE
Cascade merge operation,級聯更新(合並)操作。
當one中的數據改變,會相應地更新Course中的數據。
CascadeType.DETACH
Cascade detach operation,級聯脫管/遊離操作。
如果你要刪除一個實體,但是它有外鍵無法刪除,你就需要這個級聯權限了。它會撤銷所有相關的外鍵關聯。
Cascade refresh
operation,級聯刷新操作。
假設場景 有一個訂單,訂單裏面關聯了許多商品,這個訂單可以被很多人操作,那麽這個時候A對此訂單和關聯的商品進行了修改,與此同時,B也進行了相同的操作,但是B先一步比A保存了數據,那麽當A保存數據的時候,就需要先刷新訂單信息及關聯的商品信息後,再將訂單及商品保存。(來自“汪三”的簡書)
加載的理解:
1、FetchType.LAZY:懶加載,加載一個實體時,定義懶加載的屬性不會馬上從數據庫中加載。 2、FetchType.EAGER:急加載,加載一個實體時,定義急加載的屬性會立即從數據庫中加載。 3、比方User類有兩個屬性,name跟address,就像百度知道,登錄後用戶名是需要顯示出來的,此屬性用到的幾率極大,要馬上到數據庫查,用急加載; 而用戶地址大多數情況下不需要顯示出來,只有在查看用戶資料是才需要顯示,需要用了才查數據庫,用懶加載就好了。所以,並不是一登錄就把用戶 的所有資料都加載到對象中,於是有了這兩種加載模式。
多的一方默認使用饑餓加載,一的一方默認使用懶加載。當多的一方使用delete時,沒有級聯操作時,即使是維護方(維護方一定要指定)也能做刪除操作。但是如果此時一的一方使用饑餓加載,那麽多的一方使用delete時會報錯:org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations)。
那怎麽辦?解除要刪除對象的多對一關系,兩方都要設置,因為此時一的一方已經加載了多的一方,做法比如(order.getTblUser().getTblOrders().remove(order);
order.setTblUser(null);)。本來我以為維護方只要設置order.setTblUser(null)即可。但因為session緩存中一的一方已經有了它所對應的所有多的一方,此時它不能被刪。
---------------------
原文:https://blog.csdn.net/u010082453/article/details/43339031
OPTIONAL的理解:
如果為true,在你數據庫插入的時候,就不可以為空
一對多關系與多對一關系
- 一對多關系即數據庫中的一行數據關聯另一個數據庫中的多行關系。多對一與之相反。
- 一對多與多對一關系也可能會有中間表關聯兩者。但是我們一般不建議使用中間表。使用mapperBy可以避免系統生成中間表(會在多的一方數據庫中增加一個字段記錄外鍵)。
- 這兩個關系中的mappedBy一般聲明於一的一方,即一的一方為被維護方。
-
當使用單向關聯時,由父類管理關聯關系,子類無法管理,而這時,父親知道自己的兒子,但是,從兒子對象不知道父親是誰。
單向關聯時,只指定<one-to-many>
當使用雙向關聯時,關聯關系的管理可以通過inverse指定,這時,兒子能清楚的知道自己的父親是誰。 雙向關聯時,還要指定<many-to-one> 多對多關系 是關系數據庫中兩個表之間的一種關系, 該關系中第一個表中的一個行可以與第二個表中的一個或多個行相關。第二個表中的一個行也可以與第一個表中的一個或多個行相關。
如果我們通過學生與課程的關系來說明多對多關系:一位學生,會修多門課程;而一門課程,也會被多位學生修習。此時,雙方的關系即為多對多關系。
擁有多對多關系的兩個實體將會有一個中間表來記錄兩者之間的關聯關系。
作者:三汪
鏈接:https://www.jianshu.com/p/54108abb070f
這是@Onetoone
package edu.zut.cs.zutnlp.platform.dao; import edu.zut.cs.zutnlp.platform.base.domain.BaseEntity; import javax.persistence.*; @Table(name = "ONE1") @Entity public class One1 extends BaseEntity { @Column(name = "NAME") private String name; @OneToOne(cascade =CascadeType.ALL)//看這裏看這裏!!!!!!!!!!!!
package edu.zut.cs.zutnlp.platform.dao; import edu.zut.cs.zutnlp.platform.base.domain.BaseEntity; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; @Table @Entity public class One2 extends BaseEntity {//這裏的BaseEntity是我寫的抽象層代碼,裏面也就是序列化了一下,還有個baseDao,baseDao就配置了一下Jpa接口。 @Column(name = "NAME") private String name; public String getAge() { return age; } public void setAge(String age) { this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Column(name = "Age") private String age; }
package edu.zut.cs.zutnlp.platform.dao; import edu.zut.cs.zutnlp.platform.base.dao.GenericDaoTestCase; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; public class One1DaoTest extends GenericDaoTestCase<Long, One1,One1Dao> {// @Autowired One1Dao one1Dao; @Autowired One2Dao one2Dao; public void setOne2Dao(One2Dao one2Dao) { this.one2Dao = one2Dao; } public void setOne1Dao(One1Dao one1Dao) { this.one1Dao = one1Dao; this.dao=this.one1Dao; } @Test public void set(){ One1 one1=new One1(); // one1.setName("2"); // One2 one2=new One2(); // one2.setName("2de"); // one2.setAge("15"); // one1.setOne2(one2); one1=this.one1Dao.findByOne1_name("1"); this.one1Dao.delete(one1); System.out.println("刪除成功"); } }
!!!!!!!我刪除了one1,就可以刪除了one2,保存,更新,都可以 private One2 one2; public String getName() { return name; } public void setName(String name) { this.name = name; } public One2 getOne2() { return one2; } public void setOne2(One2 one2) { this.one2 = one2; } }
此博文只是作為筆者學習記錄之用,如有冒犯還請聯系我
一對多,多對多,一對一的理解