天天看點

一對多,多對多,一對一的了解

關系維護方和被維護方的了解:關系維護方就是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>     多對多關系 是關系資料庫中兩個表之間的一種關系, 該關系中第一個表中的一個行可以與第二個表中的一個或多個行相關。第二個表中的一個行也可以與第一個表中的一個或多個行相關。

    如果我們通過學生與課程的關系來說明多對多關系:一位學生,會修多門課程;而一門課程,也會被多位學生修習。此時,雙方的關系即為多對多關系。

    擁有多對多關系的兩個實體将會有一個中間表來記錄兩者之間的關聯關系。 當兩個類(a,b)使用@ManyToMany注解時,會産生一個中間表a_b,該中間表表示兩個類的關聯關系,此時有兩種情況:隻有一端(類)維護該關聯關系,兩端(類)均可維護該關聯關系。比如News和Label,一個News新聞可以有多個屬性Label,一個Label下可以有多個屬性,是以需要多對多

      若僅News端可維護該關聯關系,則意為隻能通過向News類對象的集合屬性labels中添加Label類的對象來更改中間表,即維護關聯關系。 在labels中設定Set<News>集合上設定(mappedBy=“**”),**是News的屬性。比如在New上設定,private Set News,然後在labels上設定mappedBy=“labels”

    private Set<News> news = new HashSet<News>();說明這個

    labels

    被news維護,你看聲明在Label類裡面嘛,但是**是在News裡嘛。是以呢,是被News維護啦,這是我友善記啦。

    https://blog.csdn.net/qq_37720278/article/details/75736294   若兩邊都維護需要設定@JoinTable,就是設定中間表了 @JoinTable(name = "new_label", joinColumns = { @JoinColumn(name = "newsId", referencedColumnName = "newId") }, inverseJoinColumns = { @JoinColumn(name = "labelId", referencedColumnName = "labelId") })

    多對多中,joinColumns寫的都是本表在中間表的外鍵名稱, inverseJoinColumns寫的是另一個表在中間表的外鍵名稱。 @JoinTable的屬性:https://blog.csdn.net/jiangyu1013/article/details/79503581 屬性referencedColumnName标注的是所關聯表中的字段名,若不指定則使用的所關聯表的主鍵字段名作為外鍵  

targetEntity的了解:

用于指定關聯的類

@ManyToMany(targetEntity = **.class)

   @Onetoone,@Onetomany,@Many-to-one ,@ManytoMany加一個就相當于加一個關系,一個類中加,就是單向,兩個類加,就是雙向。

這是@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;
    }
}      

此博文隻是作為筆者學習記錄之用,如有冒犯還請聯系我

轉載于:https://www.cnblogs.com/czrb/p/9949251.html