Hibernate中的一对多与多对一映射
Posted 十三弦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate中的一对多与多对一映射相关的知识,希望对你有一定的参考价值。
1.需求
一个部门有多个员工; 【一对多】
多个员工,属于一个部门 【多对一】
2.实体Bean设计
Dept:
public class Dept { private int depId; private String depName; private Set<Employee> emps = new HashSet<Employee>(); set... get... }
Employee:
public class Employee { private int empId; private String empName; private double salary; private Dept dept; set... get... }
3.配置映射文件
Dept.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 package="com.juaner.hibernate.department"> <class name="Dept" table="t_dept"> <!--主键--> <id name="depId"> <generator class="native"/> </id> <property name="depName" column="deptName" type="string"/> <!--一对多关联映射的配置--> <set name="emps" table="t_employee" > <!--外键字段--> <key column="dept_id"></key> <!--一对多关系--> <one-to-many class="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 package="com.juaner.hibernate.department"> <class name="Employee" table="t_employee"> <!--主键--> <id name="empId" column="empId"> <generator class="native"/> </id> <property name="empName" column="empName" type="string"/> <property name="salary" column="salary"/> <!--多对一映射--> <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one> </class> </hibernate-mapping>
4.保存数据
- 使用“一”的一方来设置关联
@Test public void test1(){ Session session = sf.openSession(); session.beginTransaction(); //部门对象 Dept dept = new Dept(); dept.setDepName("开发部"); //员工对象 Employee employee = new Employee(); employee.setEmpName("张三"); employee.setSalary(1000); Employee employee2 = new Employee(); employee2.setEmpName("李四"); employee2.setSalary(2000); dept.getEmps().add(employee); dept.getEmps().add(employee2); session.save(dept); session.save(employee); session.save(employee2); session.getTransaction().commit(); session.close(); }
此时会执行5条sql语句,其中最后两条update语句用来设置关联:
Hibernate: insert into t_dept (deptName) values (?) Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?) Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?) Hibernate: update t_employee set dept_id=? where empId=? Hibernate: update t_employee set dept_id=? where empId=?
- 使用“多”的一方来设置关联
@Test public void test2(){ Session session = sf.openSession(); session.beginTransaction(); //部门对象 Dept dept = new Dept(); dept.setDepName("人事部"); //员工对象 Employee employee = new Employee(); employee.setEmpName("张三"); employee.setSalary(1000); Employee employee2 = new Employee(); employee2.setEmpName("李四"); employee2.setSalary(2000); employee.setDept(dept); employee2.setDept(dept); //先保存一的一方,再保存多的一方,关系会自动维护,减少不必要的语句 session.save(dept); session.save(employee); session.save(employee2); session.getTransaction().commit(); session.close(); }
此时只执行三条sql语句:
Hibernate: insert into t_dept (deptName) values (?) Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?) Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
5.inverse属性
inverse属性用来设置是否控制反转。在一对多的映射中,只能在“一”的一方配置,默认值为false,即“一”的一方掌握控制权。inverse的值对数据的影响如下:
- 保存数据 有影响
如果设置控制反转,即inverse=true, 然后通过部门方维护关联关系。在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护。即外键字段为NULL
- 获取数据 无影响
- 解除关联关系 有影响
inverse=false, 可以解除关联
inverse=true, 当前方没有控制权,不能解除关联关系(不会生成update语句,也不会报错)
- 删除数据对关联关系 有影响
inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据
inverse=true, 没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束! 如果删除的记录没有被引用,可以直接删除
6.cascade属性
cascade属性用来设置级联方式,它有4个值:
none 不级联操作, 默认值
save-update 级联保存或更新
delete 级联删除
all 级联保存、更新、删除
以上是关于Hibernate中的一对多与多对一映射的主要内容,如果未能解决你的问题,请参考以下文章