源自 imooc 的学习

       多对多关联是一种常见的关联关系。多对多关联关系一般采用中间表的形式来实现,即新增一张包含关联双方主键的关联表。那么,在Hibernate中如何实现多对多的关联关系呢?

       多对多关联可以使用<set>元素和<many-to-many>元素进行配置。具体如下:

1)需要在数据库底层通过添加中间表来指定关联关系;

2)在双方的实体中添加一个保存对方的集合;

3)在双方的映射文件中使用<set>元素和<many-to-many>元素进行关联关系的配置。

       以项目和员工的关系为例,一个项目可以有员工,一个员工可以参与多个项目,项目与员工是多对多的关系。

实现如下:

创建一个名为 hibernate-many2many 的项目,目录结构如下:

Hibernate中的多对多关联_多对多关联

        首先在MySQL数据库中创建一个名为 hibernate2 的数据库,执行如下SQL语句,创建项目project 和 员工 employee表:



CREATE TABLE project (
proid INT PRIMARY KEY ,
proname VARCHAR (20) NOT NULL
);

CREATE TABLE employee (
empid INT PRIMARY KEY ,
empname VARCHAR (20)
);

CREATE TABLE proemp (
rproid INT ,
rempid INT
);

ALTER TABLE proemp ADD CONSTRAINT fk_rproid FOREIGN KEY (rproid) REFERENCES project(proid);
ALTER TABLE proemp ADD CONSTRAINT fk_rempid FOREIGN KEY (rempid) REFERENCES employee(empid);

       在 com.imooc.entity 包中创建Employee持久化类:



package com.imooc.entity;

import java.util.HashSet;
import java.util.Set;

/**
* Created by DreamBoy on 2016/5/19.
*/

/**
* 员工类
*/
public class Employee {
private int empid;
private String empname;
//添加一个项目的集合
private Set<Project> projects = new HashSet<Project>();

public Employee() {
}

public Employee(int empid, String empname) {
this.empid = empid;
this.empname = empname;
}

public Employee(int empid, String empname, Set<Project> projects) {
this.empid = empid;
this.empname = empname;
this.projects = projects;
}

public int getEmpid() {
return empid;
}

public void setEmpid(int empid) {
this.empid = empid;
}

public String getEmpname() {
return empname;
}

public void setEmpname(String empname) {
this.empname = empname;
}

public Set<Project> getProjects() {
return projects;
}

public void setProjects(Set<Project> projects) {
this.projects = projects;
}
}

       在com.imooc.entity 包中创建 Project持久化类:



package com.imooc.entity;

import java.util.HashSet;
import java.util.Set;

/**
* Created by DreamBoy on 2016/5/19.
*/

/**
* 项目类
*/
public class Project {
private int proid;
private String proname;
//添加一个员工的集合
private Set<Employee> employees = new HashSet<Employee>();

public Project() {
}

public Project(int proid, String proname) {
this.proid = proid;
this.proname = proname;
}

public Project(int proid, String proname, Set<Employee> employees) {
this.proid = proid;
this.proname = proname;
this.employees = employees;
}

public int getProid() {
return proid;
}

public void setProid(int proid) {
this.proid = proid;
}

public String getProname() {
return proname;
}

public void setProname(String proname) {
this.proname = proname;
}

public Set<Employee> getEmployees() {
return employees;
}

public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
}

       在 com.imooc.entity 包中创建对应的映射配置文件:

Employee.hbm.xml



<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

<class name="com.imooc.entity.Employee" table="employee">
<id name="empid" column="empid" type="java.lang.Integer">
<generator class="assigned"/>
</id>
<property name="empname" type="java.lang.String">
<column name="empname" length="20" not-null="true"/>
</property>
<!-- 多对多关联关系 -->
<set name="projects" table="proemp" inverse="true">
<!-- 关联的外键 -->
<key column="rempid"></key>
<!-- 集合中关联的持久化类和外键 -->
<many-to-many class="com.imooc.entity.Project" column="rproid"></many-to-many>
</set>
</class>
</hibernate-mapping>

Project.hbm.xml



<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>

<class name="com.imooc.entity.Project" table="project">
<id name="proid" column="proid" type="java.lang.Integer">
<generator class="assigned"/>
</id>
<property name="proname" type="java.lang.String">
<column name="proname" length="20" not-null="true"/>
</property>
<!-- 配置多对多关联关系 -->
<set name="employees" table="proemp" cascade="all">
<!-- 指定关联的外键列 -->
<!-- 在关联表中项目的id,它是关联的外键 -->
<key column="rproid"></key>
<many-to-many class="com.imooc.entity.Employee" column="rempid"/>
</set>
</class>
</hibernate-mapping>

项目的配置文件 hibernate.cfg.xml

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD//EN"
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="connection.username">root</property>
<property name="connection.password"></property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<!-- 下面的 hibernate 指的是 数据库名,即所用的数据库 -->
<property name="connection.url">jdbc:mysql:///hibernate2?useUnicode=true&characterEncoding=UTF-8</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

<property name="show_sql">true</property>
<!--<property name="format_sql">true</property>-->
<!--<property name="hbm2ddl.auto">create</property>-->
<property name="hbm2ddl.auto">update</property>

<!-- 指定映射文件的路径 -->
<mapping resource="com/imooc/entity/Employee.hbm.xml"/>
<mapping resource="com/imooc/entity/Project.hbm.xml"/>

<!-- DB schema will be updated if needed -->
<!-- <property name="hbm2ddl.auto">update</property> -->
</session-factory>
</hibernate-configuration>

       在 com.imooc.test 包中创建 Test.java 测试类:

Test.java

package com.imooc.test;

/**
* Created by DreamBoy on 2016/5/19.
*/

import com.imooc.entity.Employee;
import com.imooc.entity.Project;
import com.imooc.util.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.Transaction;

import java.io.Serializable;

/**
* 多对多关联关系的配置
* 同时建立了Project和Employee之间的双向多对多的关联关系
*
* 关联关系的维护?
* 在 Employee.hbm.xml 的 set 节点中 inverse属性设置为true,
* 表示关联关系的维护交由Project方来处理。
*
* 设置级联操作?
* 保存project对象时,会自动保存project对象拥有的employ员工信息
* 在 Project.hbm.xml 的 set 节点中 cascade属性设置为all,
* 表示对project对象的所有操作都进行级联。
*
* 总结:
* 关联关系的维护交由Project方来处理,并且在保存Project对象时会一并保存Employee对象。
*/
public class Test {
public static void main(String[] args) {
Project project1 = new Project(1001, "项目1");
Project project2 = new Project(1002, "项目2");
Employee employee1 = new Employee(1, "小小");
Employee employee2 = new Employee(2, "小白");

//参加项目1的员工有 employee1 和 employee2
project1.getEmployees().add(employee1);
project1.getEmployees().add(employee2);

//参加项目2的员工有 employee1
project2.getEmployees().add(employee1);

Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();

//因为设置了级联操作,所以当保存project对象时,会自动级联保存对应所拥有的employee对象信息
session.save(project1);
session.save(project2);
tx.commit();
HibernateUtil.closeSession(session);

}
}

运行结果如下:

Hibernate中的多对多关联_java_02