碼農小汪-Hibernate學習8-hibernate關聯關係註解表示@OneToMany mappedBy @ManyToMany @JoinTable

來源:互聯網
上載者:User

標籤:unique   new   碼農   地方   資料庫   建立   報錯   標識   雙向   

近期我也是有點鬱悶,究竟是程式中處理關聯關係。還是直接使用外鍵處理關聯關係呢?這個的說法不一致!程式中處理這樣的關聯關係的話。自己去維護這樣的約束。這樣的非常樂觀的一種做法!或者是直接在資料庫中處理這樣的直接的外部索引鍵關聯,悲觀的做法!剛剛看到個文章。有的公司表中一個外鍵都沒得。直接在程式中處理這樣的關聯關係。假設在Hibernate中處理外鍵關係的話。我們首先得有個主表的對象吧,然後在建立外鍵。感覺有點囉嗦。為啥不直接操作呢!

我僅僅要曉得你這個Id是外鍵即可了。各有各的說法。我想你也在思考這個問題。

現實的世界中確實非常少有孤立純在的東西。大多都是兩者之間純在某種關係的。有單向關係 僅僅能通過老師訪問學生。或者學生訪問老師
或者雙向關係 兩個都能夠相互的訪問

單向關係
1-1
1-N
N-1
N-N
雙向關係
1-1
1-N
N-N

單向N_1關聯是最多的,多個人住同一個地址。我們僅僅須要從人這一端知道他的住址即可了,不是必需知道某個地址的使用者。

為了讓我們兩個持久化實體關聯。程式在N的一端添加持久化實體的一個屬性,該屬性指向引用1的那一端的關聯實體
對於N-1(不管是單向關聯還是雙向關聯),都僅僅須要在N的一端使用@ManyToONe修飾關聯實體的屬性
有以下的一些屬性,事實上之前我也說過的,非常easy忘記。沒事的時候自己看看

屬性 說明
Cascade 級聯操作策略CascadeType.ALL….
Fetch 抓取關聯實體的策略,之前說過FechType.Lazy 延遲和馬上
targetEntity 該屬性的關聯實體的類名,在預設情況下通過反射獲得類名

預設情況下我們的targetEntity無需指定這個屬性的。但在一些特殊的情況下,比如使用@[email protected] 修飾 1-N N-N關聯的時候。關聯實體集合不帶泛型資訊就必須指定了

不需連線的N-1

無串連也就是不須要第三張表,維護我們的關聯關係。對於N_1關聯關係,我們僅僅須要在N的一端添加一列外鍵即可。

讓外鍵的值記錄到該屬性的實體即可。

Hibernate使用@JoinColumn來修飾代表關聯實體的屬性,用於映射底層的外鍵列。

這樣的就不使用串連表了

好啦,我們看一下範例

多個人相應同一個地址

@Entity@Table(name="person_inf")public class Person{    @Id @Column(name="person_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer id;    private String name;    private int age;    // 定義該Person實體關聯的Address實體    @ManyToOne(targetEntity=Address.class)    // 映射外鍵列,指定外鍵列的列名為address_id、不同意為空白    @JoinColumn(name="address_id" , nullable=false)    @Cascade(CascadeType.ALL)    private Address address;    ........}Address 裡面非常正常就一個Id。和地址具體

他們建立的表什麼樣子呢?
person_inf
person_id age name address_id
address_inf
address_id addressDetail

怎樣操作對象呢,由於address_id 是一個外鍵。

假設我們儲存一個Person對象在我們的表中的話。我們應該首先有一個Address 對象吧。

能夠是存在資料庫中的。也能夠才瞬態對象。我們在插入的時候級聯操作。會先插入address_inf這個表中,然後才幹夠使用外接啦。不然會報錯的,由於沒有存在的外鍵,肯定不行啦~

Session session = HibernateUtil.currentSession();    Transaction tx = session.beginTransaction();    // 建立一個Person對象    Person p = new Person();    // 建立一個瞬態的Address對象    Address a = new Address("廣州天河");              p.setName("Test");    p.setAge(21);    // 設定Person和Address之間的關聯關係    p.setAddress(a);    // 持久化Person對象    session.persist(p);//級聯的插入操作哦~。地址一定先於person插入資料表中,這裡必須設定級聯操作,不然要報錯    // 建立一個瞬態的Address對象    Address a2 = new Address("上海虹口");            // 改動持久化狀態的Person對象    p.setAddress(a2);                                tx.commit();    HibernateUtil.closeSession();
有串連的N-1

我們的關聯關係的維護讓第三張表來維護啦。

對於大部分的N_1單向關係,僅僅要基於外鍵的關聯關係維護已經夠了。
假設有須要使用串連表來維護關聯關係,程式能夠使用串連表顯示的維護這樣的關係,所謂串連表就是建立第三張表格來維護我們的關係即可了。使用@JoinTable

以下的是java給的範例,除了這些屬性外,我們還能夠指定targetEntity。指定關聯的實體是哪個!

也就是產生表的是哪個表所相應的實體。

 @JoinTable(        name="CUST_PHONE",        //相對於當前實體的外鍵,的列名。

參照的列名,也就是資料表中的名字 joinColumns= @JoinColumn(name="CUST_ID", referencedColumnName="ID"), //這個也是個外鍵,僅僅是不說當前實體裡面的屬性。 inverseJoinColumns= @JoinColumn(name="PHONE_ID", referencedColumnName="ID") )

我們來看個範例就知道啦

@Entity@Table(name="person_inf")public class Person{    // 識別屬性    @Id @Column(name="person_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer id;    private String name;    private int age;    // 定義該Person實體關聯的Address實體    @ManyToOne(targetEntity=Address.class)    // 顯式使用@JoinTable映射串連表    @JoinTable(name="person_address", // 指定串連表的表名為person_address        // 指定串連表中person_id外鍵列,參照到當前實體相應表的主鍵列        joinColumns=@JoinColumn(name="person_id"            , referencedColumnName="person_id", unique=true),        // 指定串連表中address_id外鍵列,參照到當前實體的關聯實體相應表的主鍵列        inverseJoinColumns=@JoinColumn(name="address_id"            , referencedColumnName="address_id")    )    private Address address;.....
@Entity@Table(name="address_inf")public class Address{    // 識別屬性    @Id @Column(name="address_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private int addressId;    // 定義地址具體資訊的成員變數    private String addressDetail;}

這裡產生的表的話,曾經的person的表不會改變address也不會變
僅僅是添加一個外表
person_address ——table
address_id person_id
使用串連表維護關係

單向1-1關聯

看上去 1-1 和N-1 幾乎相同啊,都須要在持久化實體中添加代表關聯實體的成員變數,從代碼上看沒得什麼差別。由於N的一端和1的一端都能夠直接的訪問關聯的實體,。
不管單向的還是雙向的1-1關聯,都須要使用@OneToOne修飾關聯實體的屬性
有以下的
級聯操作,抓取屬性。optional 關聯關係是否可選。目標關聯實體的類名targetEntity.還有個重要的
mappedBy:該屬性合法的屬性值為關聯實體的屬性名稱該屬性指定關聯實體中的哪個屬性可引用當前的實體

範例:基於外鍵的單向 1-1 關聯,無串連表
@Entity@Table(name="person_inf")public class Person{    // 識別屬性    @Id @Column(name="person_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer id;    private String name;    private int age;    // 定義該Person實體關聯的Address實體    @OneToOne(targetEntity=Address.class)    // 映射名為address_id的外鍵列,參照關聯實體相應表的addres_id主鍵列    @JoinColumn(name="address_id"        , referencedColumnName="address_id" , unique=true)    private Address address;  地址肯定是獨一無二的嘛,對不正確!添加unique約束~    .....}

有串連表的也是幾乎相同,理解啦買即可了

@Entity@Table(name="person_inf")public class Person{    // 識別屬性    @Id @Column(name="person_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer id;    private String name;    private int age;    // 定義該Person實體關聯的Address實體    @OneToOne(targetEntity=Address.class)    @JoinTable(name="person_address",        joinColumns=@JoinColumn(name="person_id"            , referencedColumnName="person_id" , unique=true),        inverseJoinColumns=@JoinColumn(name="address_id"            , referencedColumnName="address_id", unique=true)    )    private Address address;    ......}

上面的東西,我相信僅僅要第一個看懂了即可了,跟著畫樣子澀。1-1嘛。肯定不能一樣的澀。

單向的1-N

1的一端要訪問N的一端。肯定的加個集合澀和前面的集合非常類似,可是如今的集合裡的元素是關聯的實體啦。對於單向的1—N關聯關係。

僅僅須要在1的一端加入set類型的成員變數,記錄全部的關聯的實體。

即可了。具體怎麼操作,我們慢慢的說來。

一個個字的打還是能夠的。添加自己的理解
@OneToMany
級聯。抓取,目標實體,mappedBy

無串連表的單向1-N

1個人有多個住處~~~貪官!

不然怎麼買的起這麼多房子,如今的樓價你又不是不知道。哼~

@Entity@Table(name="person_inf")public class Person{    @Id @Column(name="person_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer id;    private String name;    private int age;    // 定義該Person實體全部關聯的Address實體,沒有指定cascade屬性    @OneToMany(targetEntity=Address.class)    // 映射外鍵列。此處映射的外鍵列將會加入到關聯實體相應的資料表中。為啥呢?    @JoinColumn(name="person_id" , referencedColumnName="person_id")    private Set<Address> addresses        = new HashSet<>();   ........ }
這裡的外鍵列不會添加到當前實體相應的資料表中,而是添加到,關聯實體Address相應的資料表中,有點特殊!

為什麼。之前我們使用set集合的時候都必須在添加一個表記得?僅僅只是這裡添加到了關聯實體裡面去了。

而不是在添加一張表~~

N的端不維護關係,沒得變化~

有串連的1-N

@Entity@Table(name="person_inf")public class Person{    // 識別屬性    @Id @Column(name="person_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer id;    private String name;    private int age;    // 定義該Person實體全部關聯的Address實體    @OneToMany(targetEntity=Address.class)    // 映射串連表為person_address    @JoinTable(name="person_address",        // 定義串連表中名為person_id的外鍵列。該外鍵列參照當前實體相應表的主鍵列        joinColumns=@JoinColumn(name="person_id"            , referencedColumnName="person_id"),        // 定義串連表中名為address_id的外鍵列。        // 該外鍵列參照當前實體的關聯實體相應表的主鍵列        inverseJoinColumns=@JoinColumn(name="address_id"            , referencedColumnName="address_id", unique=true)    )    private Set<Address> addresses        = new HashSet<>();...}

這裡是1對N 1個人有多個住的地方,可是每一個都是不一樣的,所以要添加unique約束
由於採用串連表了,我們的Person表中沒有存在維護串連關係,能夠隨意的持久化操作。


1個person 2個adress 要插入5次操作哦
自己想想為什嗎?

單向的N-N也是須要的

@ManyToMany
N-N關係必鬚鬚要串連表啦,和有串連的1-N類似,可是要把unique約束去掉啦~
直接改動啦,上面那個~

@Entity@Table(name="person_inf")public class Person{    // 識別屬性    @Id @Column(name="person_id")    @GeneratedValue(strategy=GenerationType.IDENTITY)    private Integer id;    private String name;    private int age;    // 定義該Person實體全部關聯的Address實體    @ManyToMany(targetEntity=Address.class)    // 映射串連表為person_address    @JoinTable(name="person_address",        // 定義串連表中名為person_id的外鍵列,該外鍵列參照當前實體相應表的主鍵列        joinColumns=@JoinColumn(name="person_id"            , referencedColumnName="person_id"),        // 定義串連表中名為address_id的外鍵列,        // 該外鍵列參照當前實體的關聯實體相應表的主鍵列        inverseJoinColumns=@JoinColumn(name="address_id"            , referencedColumnName="address_id")    )    private Set<Address> addresses        = new HashSet<>();...}

碼農小汪-Hibernate學習8-hibernate關聯關係註解表示@OneToMany mappedBy @ManyToMany @JoinTable

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.