今天跟大家分享下在Hibernate中双向的多对多的映射关系
这次我们以项目和员工举个栗子,因为大家可以想象得到,在真实的环境下,一个项目肯定是对应着多个员工的,这毫无疑问,
那么同时,一个比较牛员工也能同时参与多个项目的开发,这就体现了双向多对多的关系。
首先呢,我们得弄清楚在底层数据库中表与表之间的关系,我们创建一个员工表(Employee)和项目表(Project)毫无疑问,那么我们要怎么体现出多对多的关系呢?
当然有很多种方法,这里我以单独提出一张关系表为例,也就是说,我单独创建一张表来保存员工和项目的关系,具体的实体类如下
Employee
1 package entity; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 /* 7 * 员工表 8 * */ 9 public class Employee { 10 private Integer empid;//员工编号 11 private String empname;//员工名称 12 //准备一个项目集合 13 private Set<Project> pros=new HashSet<Project>(); 14 15 16 public Set<Project> getPros() { 17 return pros; 18 } 19 public void setPros(Set<Project> pros) { 20 this.pros = pros; 21 } 22 23 24 public Employee(String empname) { 25 super(); 26 this.empname = empname; 27 } 28 public Employee(Integer empid, String empname) { 29 this.empid = empid; 30 this.empname = empname; 31 } 32 public Employee() { 33 } 34 public Integer getEmpid() { 35 return empid; 36 } 37 public void setEmpid(Integer empid) { 38 this.empid = empid; 39 } 40 public String getEmpname() { 41 return empname; 42 } 43 public void setEmpname(String empname) { 44 this.empname = empname; 45 } 46 47 }
Proemp
1 package entity; 2 /* 3 * 表示员工和项目相关联的表 4 * */ 5 public class Proemp { 6 private Integer rproid;//项目编号 7 private Integer rempid;//员工编号 8 9 10 public Proemp(Integer rproid, Integer rempid) { 11 this.rproid = rproid; 12 this.rempid = rempid; 13 } 14 public Proemp() { 15 } 16 public Integer getRproid() { 17 return rproid; 18 } 19 public void setRproid(Integer rproid) { 20 this.rproid = rproid; 21 } 22 public Integer getRempid() { 23 return rempid; 24 } 25 public void setRempid(Integer rempid) { 26 this.rempid = rempid; 27 } 28 29 }
Project
1 package entity; 2 3 import java.util.HashSet; 4 import java.util.Set; 5 6 /* 7 * 项目表 8 * */ 9 public class Project { 10 private Integer proid;//项目编号 11 private String proname;//项目名称 12 //声明员工集合 13 private Set<Employee> emps=new HashSet<Employee>(); 14 15 16 public Set<Employee> getEmps() { 17 return emps; 18 } 19 public void setEmps(Set<Employee> emps) { 20 this.emps = emps; 21 } 22 23 24 public Project(String proname) { 25 this.proname = proname; 26 } 27 public Integer getProid() { 28 return proid; 29 } 30 public void setProid(Integer proid) { 31 this.proid = proid; 32 } 33 public String getProname() { 34 return proname; 35 } 36 public void setProname(String proname) { 37 this.proname = proname; 38 } 39 public Project(Integer proid, String proname) { 40 this.proid = proid; 41 this.proname = proname; 42 } 43 public Project() { 44 } 45 }
这样我们的实体类就全部创建完毕,接下来我们就可以配置映射关系文件了,既然是双向的多对多的关系,那么肯定少不了<set></set>标签
Project.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping package="entity"> 7 <class name="Project" table="project"> 8 <id name="proid" column="proid"> 9 <generator class="increment" /> 10 </id> 11 <property name="proname" type="string" column="proname" /> 12 <!-- 配置多对多的关联关系 设置级联属性--> 13 <set name="emps" table="proemp" cascade="all"> 14 <key column="rproid"></key> 15 <many-to-many class="entity.Employee" column="rempid"></many-to-many> 16 </set> 17 </class> 18 </hibernate-mapping>
Employee.hbm.xml
1 <?xml version="1.0"?> 2 <!DOCTYPE hibernate-mapping PUBLIC 3 "-//Hibernate/Hibernate Mapping DTD 3.0//EN" 4 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 5 6 <hibernate-mapping package="entity"> 7 <class name="Employee" table="Employee"> 8 <id name="empid" column="empid"> 9 <generator class="increment" /> 10 </id> 11 <property name="empname" type="string" column="empname" /> 12 <!-- 配置多对多的关联配置 设置反转属性,让项目管理关系 --> 13 <set name="pros" table="proemp" inverse="true"> 14 <key column="rempid"></key> 15 <many-to-many class="entity.Project" column="rproid"></many-to-many> 16 </set> 17 </class> 18 </hibernate-mapping>
经过以上的步骤,整个配置过程就全部完成了,当然同学们别忘记了在Hibernate配置文件(大配置)中添加对两个映射文件(小配置)的引用
测试类
1 package test; 2 3 import org.hibernate.Session; 4 import org.hibernate.Transaction; 5 6 import util.HibernateUtil; 7 import entity.Employee; 8 import entity.Project; 9 10 public class Test { 11 public static void main(String[] args) { 12 /* 13 * 多对多的关联关系配置 14 * 同时配置了Project和Employee之间双向的多对多的关联关系 15 * 关联关系由Project方维护,并且在Project方设置了级联属性 16 * */ 17 //获取Session 18 Session session=HibernateUtil.currentSession(); 19 //开启事务 20 Transaction tx = session.beginTransaction(); 21 //构建两个项目 22 Project pro1=new Project("项目一"); 23 Project pro2=new Project("项目二"); 24 //构建多个员工 25 Employee emp1=new Employee("巴黎的雨季"); 26 Employee emp2=new Employee("盛夏的果实"); 27 Employee emp3=new Employee("听风"); 28 Employee emp4=new Employee("黎明前的黑暗"); 29 30 //将员工123加入项目一 31 pro1.getEmps().add(emp1); 32 pro1.getEmps().add(emp2); 33 pro1.getEmps().add(emp3); 34 //将员工234加入项目二 35 pro2.getEmps().add(emp2); 36 pro2.getEmps().add(emp3); 37 pro2.getEmps().add(emp4); 38 39 //保存项目一和项目二 40 session.save(pro1); 41 session.save(pro2); 42 //提交事务 43 tx.commit(); 44 //关闭连接 45 HibernateUtil.closeSession(); 46 } 47 }
以上代码,我们可以发现我们仅仅保存了项目,并没有手动的添加保存员工的代码,也没有手动添加保存员工和项目之间关系的表的代码
我们可以看到Hibernate帮我们生成的sql
Hibernate很智能的通过配置文件帮我们生成了我们需要的sql,这就是面向对象思想的体现,我们自始至终都只关注了项目这个对象就完成了我们所需要的操作
我们可以看看数据库中的记录