hibernate關聯映射,hibernate關聯

來源:互聯網
上載者:User

hibernate關聯映射,hibernate關聯
本文可作為北京尚學堂馬士兵hibernate課程的學習筆記。
hibernate的映射,主要分為一對一,一對多,多對一,多對多,同時還要單向與雙向的區別。
OK,不要糾結於名字,我們開始看例子。


一對一單向老公是一個實體,老婆也是一個實體。
一個老公只有一個老婆,同時一個老婆也只有一個老公。
上面的關係就叫做一對一。
什麼叫單向呢。
看代碼:

package com.bjsxt.hibernate;@Entitypublic class Husband {    private int id;    private String name;    private Wife wife;        @Id    @GeneratedValue    public int getId() {        return id;    }        @OneToOne    @JoinColumn(name="wifeId")    public Wife getWife() {        return wife;    }    //省略get set}package com.bjsxt.hibernate;@Entitypublic class Wife {    private int id;    private String name;        @Id    @GeneratedValue    public int getId() {        return id;    }    //省略get set}


看上面的代碼,老公裡面有老婆的引用,而老婆裡面並沒有老婆的引用。
換句話說在代碼層次上,根據老公我們可以獲得他的老婆,但是根據老婆無法獲得老公。(這就是單向)

我們看看它啟動並執行代碼
package com.bjsxt.hibernate;import org.hibernate.cfg.AnnotationConfiguration;import org.hibernate.tool.hbm2ddl.SchemaExport;public class Test {    public static void main(String[] args) {        new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);        }}
在hibernate的設定檔裡
加上
<property name="hbm2ddl.auto">update</property>
結果
19:41:04,229 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Husband (        id integer not null auto_increment,        name varchar(255),        wifeId integer,        primary key (id)    )19:41:04,549 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Wife (        id integer not null auto_increment,        name varchar(255),        primary key (id)    )19:41:04,880 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    alter table Husband        add index FKAEEA401B109E78ED (wifeId),        add constraint FKAEEA401B109E78ED        foreign key (wifeId)        references Wife (id)

先給husband加了一個欄位,wifeId,然後讓他作為外鍵引用wife表的id欄位。
大家可以看到,@JoinColumn(name="wifeId")這個元標籤指示了husband表內部那那個關聯欄位的名字。
如果沒有這個元標籤呢?
那麼關聯欄位就是是:wife_id。即tableName_primarykey。
如果把 @onetoone寫到Wife裡(husband裡沒有onotoone的標籤),那麼我們就能從wife獲得husband了(在代碼層次)。



一對一雙向如果我既想從husband裡取得wife,也想從wife裡取得husband。那咋辦?
把husband裡的標籤複製一遍就OK了嘛。
package com.bjsxt.hibernate;@Entitypublic class Wife {    private int id;    private String name;    private Husband husband;        @Id    @GeneratedValue    public int getId() {        return id;    }        @OneToOne    @JoinColumn(name="husbandId")    public Husband getHusband() {        return husband;    }}

OK,上面的代碼裡,wife也可以取到husband了。
我們看看hibernate產生的sql
create table Husband (        id integer not null auto_increment,        name varchar(255),        wifeId integer,        primary key (id)    )19:53:20,487 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Wife (        id integer not null auto_increment,        name varchar(255),        husbandId integer,        primary key (id)    )19:53:20,824 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    alter table Husband        add index FKAEEA401B109E78ED (wifeId),        add constraint FKAEEA401B109E78ED        foreign key (wifeId)        references Wife (id)19:53:21,421 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    alter table Wife        add index FK292331CE01A6E1 (husbandId),        add constraint FK292331CE01A6E1        foreign key (husbandId)        references Husband (id)
看見了吧,wife裡面有外鍵,husband裡面也有外鍵!
這不是冗餘了嘛。
把wife類改成下面的樣子
    @OneToOne(mappedBy="wife")    public Husband getHusband() {        return husband;    }
這個mappedBy的意思是說,我(Wife這個類)和husband這個類是一對一關聯的,但是關聯的外鍵由husband類的getWife方法控制。
運行一下。
20:03:18,611 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Husband (        id integer not null auto_increment,        name varchar(255),        wifeId integer,        primary key (id)    )20:03:18,618 ERROR org.hibernate.tool.hbm2ddl.SchemaExport:348 - Unsuccessful: create table Husband (id integer not null auto_increment, name varchar(255), wifeId integer, primary key (id))20:03:18,618 ERROR org.hibernate.tool.hbm2ddl.SchemaExport:349 - Table 'husband' already exists20:03:18,619 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Wife (        id integer not null auto_increment,        name varchar(255),        primary key (id)    )20:03:18,933 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    alter table Husband        add index FKAEEA401B109E78ED (wifeId),        add constraint FKAEEA401B109E78ED        foreign key (wifeId)        references Wife (id)
資料庫裡,wife表裡沒有外鍵了。
但是,在代碼層次我們依然可以從Wife類裡獲得Husband。

注意上面的 @OneToOne(mappedBy="wife")
只有是雙向關聯,最好就都寫上mappedBy,兩張表有一個外鍵就夠了。



多對一單向關聯每個人都會有很多個夢想,但是每一個夢想只屬於某一個具體的人。
我們先不管java代碼上如何?,在資料庫裡。
上面的兩張表,一個是person,裡面就是id,name
再就是dream表,一個id,一個description。
那麼它們的外鍵放在哪張表裡呢?
放在dream裡,換言之,dream表裡有一個欄位叫personId。
這個的原因,不用解釋。
所有一對多,多對一的關係,在資料庫裡,外鍵都是放在多的一方裡的。
為什麼。自己想。


看代碼
package com.bjsxt.hibernate;@Entitypublic class Dream {    private int id;    private String description;        private Person person;        @Id    @GeneratedValue    public int getId() {        return id;    }    @ManyToOne    @JoinColumn(name="personId")    public Person getPerson() {        return person;    }    //省略get set}package com.bjsxt.hibernate;@Entitypublic class Person {    private int id;    private String name;        @Id    @GeneratedValue    public int getId() {        return id;    }        //省略get set}
從代碼層次上看"多對一單向"
就是我可以從多的一方(dream)裡獲得一的那一方(person)。
因為是單向,所以不能從person獲得他所有的dream。
OK,產生的表裡,dream裡有personid。
20:20:21,970 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Dream (        id integer not null auto_increment,        description varchar(255),        personId integer,        primary key (id)    )20:20:22,264 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Person (        id integer not null auto_increment,        name varchar(255),        primary key (id)    )20:20:22,765 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    alter table Dream        add index FK3F397E3C1409475 (personId),        add constraint FK3F397E3C1409475        foreign key (personId)        references Person (id)



一對多單向關聯還是人與夢想的例子。
我想在代碼層次,通過人獲得他的所有的夢想,怎麼辦?
首先在dream類裡刪除person的引用
package com.bjsxt.hibernate;@Entitypublic class Person {    private int id;    private String name;    private Set<Dream> dreams=new HashSet<>();        @Id    @GeneratedValue    public int getId() {        return id;    }    @OneToMany    @JoinColumn(name="psrsonId")    public Set<Dream> getDreams() {        return dreams;    }    }


OK,大功告成。
建表語句和上面的一樣。
裝dream的集合類為什麼是set?list行不,map行不?
都行。
但是記著,資料庫裡面的記錄是無序且不相等的。
你說用哪個?


不管是oneToMany還是manyToMany,加的 @JoinColumn(name="abc")
都是在多的一方加入指向少的一方的名叫abc的外鍵。


一對多雙向關聯(多對一雙向關聯)下面的例子,大家猜也猜到了,我既想從dream獲得它所屬的person,還想從person獲得他所有的dream。
我們看代碼:
package com.bjsxt.hibernate;@Entitypublic class Dream {    private int id;    private String description;        private Person person;        @Id    @GeneratedValue    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    @ManyToOne    @JoinColumn(name="personId")    public Person getPerson() {        return person;    }}package com.bjsxt.hibernate;@Entitypublic class Person {    private int id;    private String name;    private Set<Dream> dreams=new HashSet<>();    @Id    @GeneratedValue    public int getId() {        return id;    }    @OneToMany(mappedBy="person")    public Set<Dream> getDreams() {        return dreams;    }}
ok,我們可以在代碼裡,通過dream獲得person也可以通過person獲得dream



多對多單向關聯例子很簡單,一個老師可以教多個學生,一個學生可以被多個老師教。
單向是說,要麼老師能"知道"自己的學生,要麼學生能知道自己的老師。
我們先看老師能"知道"自己學生的代碼。

package com.bjsxt.hibernate;@Entitypublic class Student {    private int id;    private String name;        @Id    @GeneratedValue    public int getId() {        return id;    }}OK,學生裡面沒有老師的引用。package com.bjsxt.hibernate;@Entitypublic class Teacher {    private int id;    private String name;    private Set<Student> students = new HashSet<Student>();    @Id    @GeneratedValue    public int getId() {        return id;    }        @ManyToMany    @JoinTable(name="t_s",        joinColumns={@JoinColumn(name="teacher_id")},        inverseJoinColumns={@JoinColumn(name="student_id")}        )    public Set<Student> getStudents() {        return students;    }}
看結果:
21:10:35,854 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Student (        id integer not null auto_increment,        name varchar(255),        primary key (id)    )21:10:36,192 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table Teacher (        id integer not null auto_increment,        name varchar(255),        primary key (id)    )21:10:36,643 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    create table t_s (        teacher_id integer not null,        student_id integer not null,        primary key (teacher_id, student_id)    )21:10:36,947 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    alter table t_s        add index FK1BF68BF77BA8A (teacher_id),        add constraint FK1BF68BF77BA8A        foreign key (teacher_id)        references Teacher (id)21:10:37,588 DEBUG org.hibernate.tool.hbm2ddl.SchemaExport:377 -    alter table t_s        add index FK1BF68AEDC6FEA (student_id),        add constraint FK1BF68AEDC6FEA        foreign key (student_id)        references Student (id)21:10:38,263  INFO org.hibernate.tool.hbm2ddl.SchemaExport:268 - schema export complete

我們看看產生的t_s表和裡面的欄位名稱應該就能明白 @JoinTable的作用
它就是在manytomany時,指定第三張表的表名和欄位。
joinColumns 指的是指向自己這個類的欄位名
inverseJoinColumns inverse是反向的意思 所以這個標籤就是執行另外那個類的欄位
如果沒有 @JoinTable這個標籤,會是什麼樣子呢?大家自己試一下。
另外,上面的代碼是從老師到學生,大家再試試從學生到老師。


多對多雙向關聯

在上面的例子裡
改變student,給它加上teacher的引用。

package com.bjsxt.hibernate;@Entitypublic class Student {    private int id;    private String name;    private Set<Teacher> teachers=new HashSet<>();        @Id    @GeneratedValue    public int getId() {        return id;    }        //記著 雙向的時候 就加上mappedBy    @ManyToMany(mappedBy="students")    public Set<Teacher> getTeachers() {        return teachers;    }}


glt likes dlf

dlf likes glt

oneToOne



相關文章

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.