집 >데이터 베이스 >MySQL 튜토리얼 >Hibernate关联关系映射之一对多关联关系
本次以一个示例方式进行演示,某个单位有多个部门,每个部门中又有很多不同的员工,在存储时需要建立一张员工表和一张部门表,存储全部的部门和员工信息,而这两张表中通过外键进行关联,从而能根据部门名称查询出该部门的所有员工,同时又能根据员工名称查
本次以一个示例方式进行演示,某个单位有多个部门,每个部门中又有很多不同的员工,在存储时需要建立一张员工表和一张部门表,存储全部的部门和员工信息,而这两张表中通过外键进行关联,从而能根据部门名称查询出该部门的所有员工,同时又能根据员工名称查询出他所在的部门。
不难看出部门与员工之间的关系是一对多的关系,相反,员工与部门之间的关系是多对一的关系。
在POJO类和映射文件自然想到使用Set集合表示一对多。
下面看一些部门类Department类
package entity; import java.util.HashSet; import java.util.Set; public class Department { private Integer id; private String name; private Set<Employee> employees = new HashSet<Employee>(); public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Set<Employee> getEmployees() { return employees; } public void setEmployees(Set<Employee> employees) { this.employees = employees; } }
该类中使用Set集合存储员工信息,表示一个部门中有多个员工。
然后看员工类。
package entity; public class Employee { private Integer id; private String name; private Department department; public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Department getDepartment() { return department; } public void setDepartment(Department department) { this.department = department; } }
该类通过一个私有的Department类的属性,表示一个员工只能属于一个部门。
下面看一下他们的映射文件的配置。
首先看Department.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="entity.Department" table="DEPARTMENT" schema="MYHR"> <id name="id" type="int"> <column name="ID" precision="22" scale="0" /> <generator class="assigned" /> </id> <property name="name" type="string"> <column name="NAME" not-null="true" /> </property> <!-- employees属性,Set集合,表示本类与Employee的一对多映射 --> <!-- class属性,表示关联的实体类型 --> <!-- key需要关联表的外键列 --> <!-- inverse属性: 默认为false:表示本方维护关联关系。 如果为true:表示本方不维护关联关系。 --> <set name="employees" inverse="false"> <key column="departmentId" /> <one-to-many class="entity.Employee" /> </set> </class> </hibernate-mapping>
其中使用
然后看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="entity.Employee" table="Employee" schema="MYHR"> <id name="id" type="int"> <column name="ID" precision="22" scale="0" /> <generator class="assigned" /> </id> <property name="name" type="string"> <column name="NAME" not-null="true" /> </property> <!-- department属性,表示本类与Department类的多对一 --> <!-- class属性,关联的实体类型 --> <!-- column属性,外键列(引用关联对象的表的主键) --> <many-to-one name="department" class="entity.Department" column="departmentId"/> </class> </hibernate-mapping>
这里通过
然后他们之间的映射关系已经搭建完毕,下面看一下测试类,使用JUtil进行测试。
package test; import static org.junit.Assert.*; import java.util.Iterator; import java.util.Set; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.Transaction; import entity.Department; import entity.Employee; import factory.HibernateSessionFactory; public class Test { private Session session = null; private Transaction tran = null; //保存对象 @org.junit.Test public void test() { session = HibernateSessionFactory.getSession(); tran = session.beginTransaction(); try { //新建对象 Department de = new Department(); de.setId(3); de.setName("研发部"); Employee e1 = new Employee(); e1.setId(1); e1.setName("张三"); Employee e2 = new Employee(); e2.setId(2); e2.setName("李四"); //建立关系映射 de.getEmployees().add(e1); de.getEmployees().add(e2); e1.setDepartment(de); e2.setDepartment(de); //保存数据 session.save(de); session.save(e1); session.save(e2); tran.commit(); } catch (Exception e) { tran.rollback(); } } //根据部门查询员工 @org.junit.Test public void getDepartment() { session = HibernateSessionFactory.getSession(); String hql = "FROM Department d where d.id = 2"; Query query = session.createQuery(hql); Department de = (Department) query.uniqueResult(); Set<Employee> set = de.getEmployees(); Iterator it = set.iterator(); while (it.hasNext()) { Employee e = (Employee) it.next(); System.out.println(e.getName()); } } //根据员工查询部门 @org.junit.Test public void getEmployee() { session = HibernateSessionFactory.getSession(); String hql = "FROM Employee e where e.id=1"; Query query = session.createQuery(hql); Employee e = (Employee) query.uniqueResult(); System.out.println(e.getName() + "属于" + e.getDepartment().getName()); } // 解除关联关系,相当于某一个员工离开原来部门,并不删除两个表中数据 // 从员工方删除 @org.junit.Test public void removeRelation() { session = HibernateSessionFactory.getSession(); tran = session.beginTransaction(); try { Department de = new Department(); de.setId(1); de.setName("宣传部"); session.save(de); Employee e = (Employee) session.get(Employee.class, 3); e.setDepartment(de); session.save(e); tran.commit(); } catch (Exception e) { tran.rollback(); } } // 删除员工方 @org.junit.Test public void deleteEmployee() { session = HibernateSessionFactory.getSession(); tran = session.beginTransaction(); try { Employee e = (Employee) session.get(Employee.class, 4); session.delete(e); tran.commit(); } catch (Exception e) { tran.rollback(); } } // 删除部门 @org.junit.Test public void deleteDepartment() { session = HibernateSessionFactory.getSession(); tran = session.beginTransaction(); try { Department de = (Department) session.get(Department.class, 1); /* * 如果没有关联的员工,能删除 * 如果有关联的员工,且inverse属性为true,由于由不能维护关联,所以会直接执行删除,就会有异常 * 如果有关联的与昂,且inverse属性为false,由于可以维护关联关系,他就会先把关联的员工的外键设为null。在删除 */ session.delete(de); tran.commit(); } catch (Exception e) { tran.rollback(); } } }