Hibernate学习笔记(五)——多对多映射

来源:互联网 发布:数据库去除重复记录 编辑:程序博客网 时间:2024/06/16 21:32

一、多对多映射的简单介绍

在之前的文章里,我们介绍了Hibernate中怎样使用一对一映射、一对多和多对一映射,现在来简单介绍一下多对多映射。多对多映射在数据库中也是很常见的一种映射关系,例如项目和员工之间就是很典型的多对多映射,一个项目中可能会涉及很多员工,同时一个员工也可能参与很多项目。在数据库中,要实现多对多映射,一种很常见的方法就是添加一个中间表来指定关联关系,即新增一张包含关联双方主键的关联表。而在Hibernate中可以通过在双方实体类中定义关联对象集合,并在双方的映射文件中配置<set>和<many-to-many>元素来实现多对多映射。下面就通过一个实例来分析以下Hibernate中的多对多映射。

二、多对多映射实例

我们就以项目和员工表作为实例来讲解多对多关系映射,首先我们要建立项目表project:
CREATE TABLE `project` (  `proid` int(11) NOT NULL,  `proname` varchar(20) NOT NULL,  PRIMARY KEY (`proid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
项目表中只有两个简单的字段项目id和项目名称。然后我们建立员工表employee:
CREATE TABLE `employee` (  `empid` int(11) NOT NULL,  `empname` varchar(20) DEFAULT NULL,  PRIMARY KEY (`empid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
表中有员工id和员工名称字段。因为项目和员工是多对多的映射关系,所以我们需要建立一张中间表proemp来表示它们的关联关系,这个表中有项目表和员工表的双方主键。
CREATE TABLE `proemp` (  `rproid` int(11) DEFAULT NULL,  `rempid` int(11) DEFAULT NULL,  KEY `fk_rproid` (`rproid`),  KEY `fk_rempid` (`rempid`),  CONSTRAINT `fk_rempid` FOREIGN KEY (`rempid`) REFERENCES `employee` (`empid`),  CONSTRAINT `fk_rproid` FOREIGN KEY (`rproid`) REFERENCES `project` (`proid`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
建立好表之后我们就可以创建两个表对应的实体类了,要实现多对多关系,我们需要在两个实体类中分别定义对方的集合,首先我们建立项目类Project。
package com.imooc.entity;import java.util.HashSet;import java.util.Set;public class Project {private int proid;private String proname;private Set<Employee> employees = new HashSet<Employee>();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;}public Project() {super();}public Project(int proid, String proname) {super();this.proid = proid;this.proname = proname;}}
然后我们定义员工类Employee:
package com.imooc.entity;import java.util.HashSet;import java.util.Set;public class Employee {private int empid;private String empname;private Set<Project> projects = new HashSet<Project>();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;}public Employee() {super();}public Employee(int empid, String empname) {super();this.empid = empid;this.empname = empname;}}
实体类定义完成后就可以创建映射文件了,我们首先创建Project.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"><!-- Generated 2016-10-5 10:14:35 by Hibernate Tools 3.4.0.CR1 --><hibernate-mapping>    <class name="com.imooc.entity.Project" table="project">        <id name="proid" type="int">            <column name="proid" />            <generator class="assigned" />        </id>        <property name="proname" type="java.lang.String">            <column name="proname" />        </property>        <!-- 实现多对多的映射关系 -->        <set name="employees" table="proemp" cascade="all">            <key>                <column name="rproid" />            </key>            <many-to-many class="com.imooc.entity.Employee" column="rempid"/>        </set>    </class></hibernate-mapping>
在这个映射文件中,我们使用<set>元素和<many-to-many>元素实现多对多的映射关系,其中table属性指定了中间表proemp,而key和many-to-many的column都指定了在中间表中关联的外键名称。我们还在使用set元素中使用cascade属性来表示级联操作,这在之前的文章中也有介绍。接下来我们就可以创建Employee.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"><!-- Generated 2016-10-5 10:14:35 by Hibernate Tools 3.4.0.CR1 --><hibernate-mapping>    <class name="com.imooc.entity.Employee" table="employee">        <id name="empid" type="int">            <column name="empid" />            <generator class="assigned" />        </id>        <property name="empname" type="java.lang.String">            <column name="empname" />        </property>        <set name="projects" table="proemp" inverse="true">            <key>                <column name="rempid" />            </key>            <many-to-many class="com.imooc.entity.Project" column="rproid"/>        </set>    </class></hibernate-mapping>
在这个映射文件里与Project.hbm.xml配置类似,只是我们使用inverse属性指定了控制权由Project来控制。配置好映射文件后我们需要在hibernate.cfg.xml文件中进行注册,在这里就不赘述了,之前也有介绍过。最后我们使用JUnit来进行测试,创建SessionFactory、Session和Transaction的过程就不介绍了,与之前的方法相同,我们直接看测试方法。
@Testpublic void testAdd() {Project project1 = new Project(1001, "项目一");Project project2 = new Project(1002, "项目二");Employee employee1 = new Employee(1, "张三");Employee employee2 = new Employee(2, "李四");project1.getEmployees().add(employee1);project1.getEmployees().add(employee2);project2.getEmployees().add(employee1);session.save(project1);session.save(project2);}
我们在这个方法里创建了两个项目和两个员工,并分别对两个项目关联不同的员工,执行插入操作后观察数据库表,我们会发现插入项目表和员工表数据成功了,同时插入中间表表示项目和员工关联关系的表也成功了。








0 0
原创粉丝点击