hibernate的Many2One、Many2Many等的使用

本文簡單講述hibernate的Many2One、One2Many和Many2Many的單雙向映射的annotation和xml的實現方式。

1.首先,先看下annotation的API文檔

2.2.5.2. 多對一(Many-to-one)

在實體屬性一級使用@ManyToOne註解來定義多對一關聯:

@Entity()
public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
        return company;
    }
    ...
}
            

其中@JoinColumn是可選的,關聯字段默認值和一對一 (one to one)關聯的情況相似, 列名爲:主體的關聯屬性名+下劃線+被關聯端的主鍵列名. 在這個例子中是company_id, 因爲關聯的屬性是companyCompany的主鍵是id.

@ManyToOne註解有一個名爲targetEntity的參數, 該參數定義了目標實體名.通常不需要定義該參數, 因爲在大部分情況下默認值(表示關聯關係的屬性類型)就可以很好的滿足要求了. 不過下面這種情況下這個參數就顯得有意義了:使用接口作爲返回值而不是常見的實體.

@Entity()
public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE}, targetEntity=CompanyImpl.class )
    @JoinColumn(name="COMP_ID")
    public Company getCompany() {
        return company;
    }
    ...
}

public interface Company {
    ...
            

對於多對一也可以通過關聯表的方式來映射。 通過@JoinTable註解可定義關聯表, 該關聯表包含了指回實體表的外鍵(通過@JoinTable.joinColumns) 以及指向目標實體表的外鍵(通過@JoinTable.inverseJoinColumns).

@Entity()
public class Flight implements Serializable {
    @ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
    @JoinTable(name="Flight_Company",
        joinColumns = @JoinColumn(name="FLIGHT_ID"),
        inverseJoinColumns = @JoinColumn(name="COMP_ID")
    )
    public Company getCompany() {
        return company;
    }
    ...
}
2.2.5.3.2. 一對多(One-to-many)

在屬性級使用 @OneToMany註解可定義一對多關聯.一對多關聯可以是雙向關聯.

2.2.5.3.2.1. 雙向(Bidirectional)

在EJB3規範中多對一這端幾乎總是雙向關聯中的主體(owner)端, 而一對多這端的關聯註解爲@OneToMany( mappedBy=... )

@Entity
public class Troop {
    @OneToMany(mappedBy="troop")
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk")
    public Troop getTroop() {
    ...
}              

Troop 通過troop 屬性和Soldier建立了一對多的雙向關聯. 在mappedBy端不必也不能再定義任何物理映射

對於一對多的雙向映射,如果要一對多這一端維護關聯關係, 你需要刪除mappedBy元素並將多對一這端的 @JoinColumn的insertable和updatable設置爲false. 很明顯,這種方案不會得到什麼明顯的優化,而且還會增加一些附加的UPDATE語句.

@Entity
public class Troop {
    @OneToMany
    @JoinColumn(name="troop_fk") //we need to duplicate the physical information
    public Set<Soldier> getSoldiers() {
    ...
}

@Entity
public class Soldier {
    @ManyToOne
    @JoinColumn(name="troop_fk", insertable=false, updatable=false)
    public Troop getTroop() {
    ...
}
2.2.5.3.2.2. 單向(Unidirectional)

通過在被擁有的實體端(owned entity)增加一個外鍵列來實現一對多單向關聯是很少見的,也是不推薦的. 我們強烈建議通過一個聯接表(join table)來實現這種關聯(下一節會對此進行解釋). 可以通過@JoinColumn註解來描述這種單向關聯關係.

@Entity
public class Customer implements Serializable {
    @OneToMany(cascade=CascadeType.ALL, fetch=FetchType.EAGER)
    @JoinColumn(name="CUST_ID")
    public Set<Ticket> getTickets() {
    ...
}

@Entity
public class Ticket implements Serializable {
    ... //no bidir
}
               

Customer 通過 CUST_ID列和Ticket 建立了單向關聯關係.

2.2.5.3.2.3. 通過關聯表處理單向關聯

通過聯接表處理單向一對多關聯是首選方式.這種關聯通過@JoinTable註解來進行描述.

@Entity
public class Trainer {
    @OneToMany
    @JoinTable(
            name="TrainedMonkeys",
            joinColumns = @JoinColumn( name="trainer_id"),
            inverseJoinColumns = @JoinColumn( name="monkey_id")
    )
    public Set<Monkey> getTrainedMonkeys() {
    ...
}

@Entity
public class Monkey {
    ... //no bidir
}
               

上面這個例子中,Trainer通過 TrainedMonkeys表和 Monkey 建立了單向關聯. 其中外鍵trainer_id關聯到Trainer (joinColumns), 而外鍵monkey_id關聯到 Monkey (inversejoinColumns).

2.2.5.3.2.4. 默認處理機制

通過聯接表來建立單向一對多關聯不需要描述任何物理映射. 表名由以下三個部分組成:主表(owner table)表名+下劃線+從表(the other side table)表名. 指向主表的外鍵名:主表表名+下劃線+主表主鍵列名 指向從表的外鍵名:主表所對應實體的屬性名+下劃線+從表主鍵列名 指向從表的外鍵定義爲唯一約束,用來表示一對多的關聯關係.

@Entity
public class Trainer {
    @OneToMany
    public Set<Tiger> getTrainedTigers() {
    ...
}

@Entity
public class Tiger {
    ... //no bidir
}
               

上面這個例子中,TrainerTiger 通過聯接表 Trainer_Tiger建立單向關聯關係, 其中外鍵trainer_id關聯到Trainer (主表表名, _(下劃線), trainer id), 而外鍵trainedTigers_id關聯到Tiger (屬性名稱, _(下劃線), Tiger表的主鍵列名).

2.2.5.3.3. 多對多(Many-to-many)
2.2.5.3.3.1. 定義

你可以通過@ManyToMany註解可定義的多對多關聯. 同時,你也需要通過註解@JoinTable描述關聯表和關聯條件. 如果是雙向關聯,其中一段必須定義爲owner,另一端必須定義爲inverse(在對關聯表進行更新操作時這一端將被忽略):

@Entity
public class Employer implements Serializable {
    @ManyToMany(
        targetEntity=org.hibernate.test.metadata.manytomany.Employee.class,
        cascade={CascadeType.PERSIST, CascadeType.MERGE}
    )
    @JoinTable(
        name="EMPLOYER_EMPLOYEE",
        joinColumns=@JoinColumn(name="EMPER_ID"),
        inverseJoinColumns=@JoinColumn(name="EMPEE_ID")
    )
    public Collection getEmployees() {
        return employees;
    }
    ...
}
               
@Entity
public class Employee implements Serializable {
    @ManyToMany(
        cascade = {CascadeType.PERSIST, CascadeType.MERGE},
        mappedBy = "employees",
        targetEntity = Employer.class
    )
    public Collection getEmployers() {
        return employers;
    }
}
               

至此,我們已經展示了很多跟關聯有關的聲明定義以及屬性細節. 下面我們將深入介紹@JoinTable註解,該註解定義了聯接表的表名, 聯接列數組(註解中定義數組的格式爲{ A, B, C }), 以及inverse聯接列數組. 後者是關聯表中關聯到Employee主鍵的列(the "other side").

正如前面所示,被關聯端不必也不能描述物理映射: 只需要一個簡單的mappedBy參數,該參數包含了主體端的屬性名,這樣就綁定雙方的關係.

2.2.5.3.3.2. 默認值

和其他許多註解一樣,在多對多關聯中很多值是自動生成. 當雙向多對多關聯中沒有定義任何物理映射時,Hibernate根據以下規則生成相應的值. 關聯表名:主表表名+_下劃線+從表表名, 關聯到主表的外鍵名:主表名+_下劃線+主表中的主鍵列名. 關聯到從表的外鍵名:主表中用於關聯的屬性名+_下劃線+從表的主鍵列名. 以上規則對於雙向一對多關聯同樣有效.

@Entity
public class Store {
    @ManyToMany(cascade = CascadeType.PERSIST)
    public Set<City> getImplantedIn() {
        ...
    }
}

@Entity
public class City {
    ... //no bidirectional relationship
}
               

上面這個例子中,Store_Table作爲聯接表. Store_id列是聯接到Store表的外鍵. 而implantedIn_id列則聯接到City表.

當雙向多對多關聯中沒有定義任何物理映射時, Hibernate根據以下規則生成相應的值 關聯表名: :主表表名+_下劃線+從表表名, 關聯到主表的外鍵名:從表用於關聯的屬性名+_下劃線+主表中的主鍵列名. 關聯到從表的外鍵名:主表用於關聯的屬性名+_下劃線+從表的主鍵列名. 以上規則對於雙向一對多關聯同樣有效.

@Entity
public class Store {
    @ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    public Set<Customer> getCustomers() {
        ...
    }
}

@Entity
public class Customer {
    @ManyToMany(mappedBy="customers")
    public Set<Store> getStores() {
        ...
    }
}
               

在上面這個例子中,Store_Customer作爲聯接表. stores_id列是聯接到Store表的外鍵, 而customers_id列聯接到City表.


2.再來看下xml的API文檔

Finally, here is an example of a unidirectional many-to-many association.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
</class>
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )

bidirectional many-to-one association is the most common kind of association. The following example illustrates the standard parent/child relationship.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <many-to-one name="address" 
        column="addressId"
        not-null="true"/>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <set name="people" inverse="true">
        <key column="addressId"/>
        <one-to-many class="Person"/>
    </set>
</class>
create table Person ( personId bigint not null primary key, addressId bigint not null )
create table Address ( addressId bigint not null primary key )
        

If you use a List, or other indexed collection, set the key column of the foreign key to not null. Hibernate will manage the association from the collections side to maintain the index of each element, making the other side virtually inverse by setting update="false" and insert="false":

<class name="Person">
   <id name="id"/>
   ...
   <many-to-one name="address"
      column="addressId"
      not-null="true"
      insert="false"
      update="false"/>
</class>

<class name="Address">
   <id name="id"/>
   ...
   <list name="people">
      <key column="addressId" not-null="true"/>
      <list-index column="peopleIdx"/>
      <one-to-many class="Person"/>
   </list>
</class>

If the underlying foreign key column is NOT NULL, it is important that you define not-null="true" on the<key> element of the collection mapping. Do not only declare not-null="true" on a possible nested <column>element, but on the <key> element.

Here is an example of a bidirectional many-to-many association.

<class name="Person">
    <id name="id" column="personId">
        <generator class="native"/>
    </id>
    <set name="addresses" table="PersonAddress">
        <key column="personId"/>
        <many-to-many column="addressId"
            class="Address"/>
    </set>
</class>

<class name="Address">
    <id name="id" column="addressId">
        <generator class="native"/>
    </id>
    <set name="people" inverse="true" table="PersonAddress">
        <key column="addressId"/>
        <many-to-many column="personId"
            class="Person"/>
    </set>
</class>
create table Person ( personId bigint not null primary key )
create table PersonAddress ( personId bigint not null, addressId bigint not null, primary key (personId, addressId) )
create table Address ( addressId bigint not null primary key )

3.Many2One單向映射的annotation版本

使用Group和User,二者爲多對一的關係,即一個Group有多個User,多個User對應一個Group

需要在User中引用Group,並在getGroup使用@ManyToOne

Group

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name="t_group")
public class Group {
	private String id;
	private String name;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
User

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {
	private String id;
	private String name;
	private Group group ;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToOne
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}
}
使用JUnit進行測試,OrMappingTest.java,注意此類在之後的測試中通用

package com.baosight.model;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

public class OrMappingTest {
	private static SessionFactory sf = null;
	@BeforeClass
	public static void beforeClass(){
		// 讀取配置文件
		Configuration cfg = new AnnotationConfiguration();
		// 得到session工廠
		sf = cfg.configure().buildSessionFactory();
	}
	@Test
	public void testSchemaExport() {
		new SchemaExport(new AnnotationConfiguration().configure()).create(false, true);
	}
	@AfterClass
	public static void afterClass(){
		// 關閉session工廠
		sf.close();
	}
}
測試結果爲:


4.Many2One單向映射的xml版本

使用School和Student,二者爲多對一的關係,即一個School有多個Student,多個Student對應一個School

需要在Student中引用School,並在Student.hbm.xml使用<many-to-one name="school" column="schoolId"></many-to-one>

School

package com.baosight.model;


public class School {
	private String id;
	private String name;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
Student
package com.baosight.model;


public class Student {
	private String id;
	private String num;
	private School school;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public School getSchool() {
		return school;
	}
	public void setSchool(School school) {
		this.school = school;
	}
	
}
School.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="School" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
</class>
</hibernate-mapping>
Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Student" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
<many-to-one name="school" column="schoolId"></many-to-one>
</class>
</hibernate-mapping>
測試結果爲:

5.One2Many單向映射的annotation版本

使用Group和User,二者爲一對多的關係,即一個Group有多個User,多個User對應一個Group

需要在Group中引用User的集合Set<User> users,並在getUsers使用@OneToMany
@JoinColumn(name="groupId")

Group

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="t_group")
public class Group {
	private String id;
	private String name;
	private Set<User> users;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@OneToMany
	@JoinColumn(name="groupId")
	public Set<User> getUsers() {
		return users;
	}
	public void setUsers(Set<User> users) {
		this.users = users;
	}
}
User

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {
	private String id;
	private String name;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
測試結果爲:

6.One2Many單向映射的xml版本

使用School和Student,二者爲一對多的關係,即一個School有多個Student,多個Student對應一個School

需要在School中引用Student的集合Set<Student> students,並在School.hbm.xml使用<set name="students">
<key column="schoolId"/>
<one-to-many class="Student"/>
</set>

School

package com.baosight.model;

import java.util.Set;


public class School {
	private String id;
	private String name;
	private Set<Student> students;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}
Student
package com.baosight.model;


public class Student {
	private String id;
	private String num;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
}
School.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="School" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="students">
<key column="schoolId"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Student" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
</class>
</hibernate-mapping>
測試結果爲:

7.Many2One/One2Many雙向映射的annotation版本

使用Group和User,二者爲多對一的關係,即一個Group有多個User,多個User對應一個Group

需要在User中引用Group,並在getGroup使用@ManyToOne

還需要在Group中引用User的集合Set<User> users,並在getUsers使用@OneToMany(mappedBy="group"),mappedBy表示映射關係由User中的group來維持

Group

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name="t_group")
public class Group {
	private String id;
	private String name;
	private Set<User> users;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@OneToMany(mappedBy="group")
	public Set<User> getUsers() {
		return users;
	}
	public void setUsers(Set<User> users) {
		this.users = users;
	}
}
User

package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
@Table(name="t_user")
public class User {
	private String id;
	private String name;
	private Group group;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToOne
	public Group getGroup() {
		return group;
	}
	public void setGroup(Group group) {
		this.group = group;
	}
}
測試結果爲:

8.Many2One/One2Many雙向映射的xml版本

使用School和Student,二者爲多對一的關係,即一個School有多個Student,多個Student對應一個School

需要在Student中引用School,並在Student.hbm.xml使用<many-to-one name="school" column="schoolId"></many-to-one>

還需要需要在School中引用Student的集合Set<Student> students,並在School.hbm.xml使用<set name="students">
<key column="schoolId"/>
<one-to-many class="Student"/>
</set>

School

package com.baosight.model;

import java.util.Set;


public class School {
	private String id;
	private String name;
	private Set<Student> students;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}
Student

package com.baosight.model;


public class Student {
	private String id;
	private String num;
	private School school;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public School getSchool() {
		return school;
	}
	public void setSchool(School school) {
		this.school = school;
	}
}
School.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="School" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="students">
<key column="schoolId"/>
<one-to-many class="Student"/>
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Student" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
<many-to-one name="school" column="schoolId"></many-to-one>
</class>
</hibernate-mapping>
測試結果:

9.Many2Many單向映射的annotation版本

使用Teacher和Student,二者爲多對多的關係,即一個Teacher有多個Student,一個Student對應多個Teacher

本例單向的意思是Teacher引用Student的集合Set<Student> students,並在getStudents使用@ManyToMany
@JoinTable(name="t_s",
joinColumns={@JoinColumn(name="teacher_id")},
inverseJoinColumns={@JoinColumn(name="student_id")}
)

Teacher

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
public class Teacher {
	private String id;
	private String name;
	private Set<Student> students;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToMany
	@JoinTable(name="t_s",
	joinColumns={@JoinColumn(name="teacher_id")},
	inverseJoinColumns={@JoinColumn(name="student_id")}
	)
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}
Student
package com.baosight.model;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
public class Student {
	private String id;
	private String name;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
}
測試結果爲:


10.Many2Many單向映射的xml版本

使用Order和Product,二者爲多對多的關係,即一個Order有多個Product,一個Product對應多個Order

本例單向的意思是需要在Order中引用Product的集合Set<Product> products,並在Order.hbm.xml使用

<set name="products" table="order_pro">
<key column="orderId"/>
<many-to-many class="Product" column="productId"/>
</set>

Order

package com.baosight.model;

import java.util.Set;


public class Order {
	private String id;
	private String name;
	private Set<Product> products;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Product> getProducts() {
		return products;
	}
	public void setProducts(Set<Product> products) {
		this.products = products;
	}
}
Product
package com.baosight.model;


public class Product {
	private String id;
	private String num;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
}
Order.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Order" table="t_order" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="products" table="order_pro">
<key column="orderId"/>
<many-to-many class="Product" column="productId"/>
</set>
</class>
</hibernate-mapping>
Product.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Product" table="t_product" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
</class>
</hibernate-mapping>
測試結果爲:


11.Many2Many雙向映射的annotation版本

使用Teacher和Student,二者爲多對多的關係,即一個Teacher有多個Student,一個Student對應多個Teacher

需要在Teacher引用Student的集合Set<Student> students,並在getStudents使用@ManyToMany
@JoinTable(name="t_s",
joinColumns={@JoinColumn(name="teacher_id")},
inverseJoinColumns={@JoinColumn(name="student_id")}
)

還需要在在Student引用Teacher的集合Set<Teacher> teachers,並在getTeachers使用@ManyToMany(mappedBy="students"),其中mappedBy表示映射關係由Teacher中的students來管理

Teacher

package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinColumns;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
public class Teacher {
	private String id;
	private String name;
	private Set<Student> students;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToMany
	@JoinTable(name="t_s",
	joinColumns={@JoinColumn(name="teacher_id")},
	inverseJoinColumns={@JoinColumn(name="student_id")}
	)
	public Set<Student> getStudents() {
		return students;
	}
	public void setStudents(Set<Student> students) {
		this.students = students;
	}
}
Student
package com.baosight.model;

import java.util.Set;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.Table;

@Entity
public class Student {
	private String id;
	private String name;
	private Set<Teacher> teachers;
	@Id
	@GeneratedValue//auto
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	@ManyToMany(mappedBy="students")
	public Set<Teacher> getTeachers() {
		return teachers;
	}
	public void setTeachers(Set<Teacher> teachers) {
		this.teachers = teachers;
	}
}
測試結果爲:

12.Many2Many雙向映射的xml版本

使用Order和Product,二者爲多對多的關係,即一個Order有多個Product,一個Product對應多個Order

需要在Order中引用Product的集合Set<Product> products,並在Order.hbm.xml使用

<set name="products" table="order_pro">
<key column="orderId"/>
<many-to-many class="Product" column="productId"/>
</set>

還需要在

需要在Product中引用Order的集合Set<Order> orders,並在Product.hbm.xml使用

<set name="orders" table="order_pro">
<key column="productId"/>
<many-to-many class="Order" column="orderId"/>
</set>

Order

package com.baosight.model;

import java.util.Set;


public class Order {
	private String id;
	private String name;
	private Set<Product> products;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public Set<Product> getProducts() {
		return products;
	}
	public void setProducts(Set<Product> products) {
		this.products = products;
	}
}
Product
package com.baosight.model;

import java.util.Set;


public class Product {
	private String id;
	private String num;
	private Set<Order> orders;
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public String getNum() {
		return num;
	}
	public void setNum(String num) {
		this.num = num;
	}
	public Set<Order> getOrders() {
		return orders;
	}
	public void setOrders(Set<Order> orders) {
		this.orders = orders;
	}
}
Order.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Order" table="t_order" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="name"></property>
<set name="products" table="order_pro">
<key column="orderId"/>
<many-to-many class="Product" column="productId"/>
</set>
</class>
</hibernate-mapping>
Product.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping package="com.baosight.model">
<class name="Product" table="t_product" dynamic-update="true">
<id name="id" >
<generator class="native"></generator>
</id>
<property name="num"></property>
<set name="orders" table="order_pro">
<key column="productId"/>
<many-to-many class="Order" column="orderId"/>
</set>
</class>
</hibernate-mapping>
測試結果:



以上即爲hibernate的Many2One/One2Many/Many2Many的內容,值得一提的是在實際的使用中多使用Many2One/One2Many,而Many2Many使用的不多。總之,這些映射關係需要在實際的使用中仔細體會。











發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章