本文簡單講述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, 因爲關聯的屬性是company, Company的主鍵是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註解可定義一對多關聯.一對多關聯可以是雙向關聯.
在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() { ... }
通過在被擁有的實體端(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 建立了單向關聯關係.
通過聯接表處理單向一對多關聯是首選方式.這種關聯通過@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).
通過聯接表來建立單向一對多關聯不需要描述任何物理映射. 表名由以下三個部分組成:主表(owner table)表名+下劃線+從表(the other side table)表名. 指向主表的外鍵名:主表表名+下劃線+主表主鍵列名 指向從表的外鍵名:主表所對應實體的屬性名+下劃線+從表主鍵列名 指向從表的外鍵定義爲唯一約束,用來表示一對多的關聯關係.
@Entity public class Trainer { @OneToMany public Set<Tiger> getTrainedTigers() { ... } @Entity public class Tiger { ... //no bidir }
上面這個例子中,Trainer和Tiger 通過聯接表 Trainer_Tiger建立單向關聯關係, 其中外鍵trainer_id關聯到Trainer (主表表名, _(下劃線), trainer id), 而外鍵trainedTigers_id關聯到Tiger (屬性名稱, _(下劃線), Tiger表的主鍵列名).
你可以通過@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參數,該參數包含了主體端的屬性名,這樣就綁定雙方的關係.
和其他許多註解一樣,在多對多關聯中很多值是自動生成. 當雙向多對多關聯中沒有定義任何物理映射時,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文檔
<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> </class>
create table Person ( personId bigint not null primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <set name="addresses"> <key column="personId" not-null="true"/> <one-to-many 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 Address ( addressId bigint not null primary key, personId bigint not null )
You should instead use a join table for this kind of 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" unique="true" 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 not null, addressId bigint not null primary key ) create table Address ( addressId bigint not null primary key )
<class name="Person"> <id name="id" column="personId"> <generator class="native"/> </id> <join table="PersonAddress" optional="true"> <key column="personId" unique="true"/> <many-to-one name="address" column="addressId" not-null="true"/> </join> </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 primary key, addressId bigint not null ) create table Address ( addressId bigint not null primary key )
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 )
<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 )
<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>
<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" unique="true" class="Address"/> </set> </class> <class name="Address"> <id name="id" column="addressId"> <generator class="native"/> </id> <join table="PersonAddress" inverse="true" optional="true"> <key column="addressId"/> <many-to-one name="person" column="personId" not-null="true"/> </join> </class>
create table Person ( personId bigint not null primary key ) create table PersonAddress ( personId bigint not null, addressId bigint not null primary key ) create table Address ( addressId bigint not null primary key )
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;
}
}
Studentpackage 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;
}
}
Studentpackage 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;
}
}
Studentpackage 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;
}
}
Productpackage 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;
}
}
Studentpackage 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;
}
}
Productpackage 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使用的不多。總之,這些映射關係需要在實際的使用中仔細體會。