一对多与多对一映射实现步骤
javaBean类
- 部门类
public class Dept {
private int deptId;
private String deptName;
private Set<Employee> emps;
public int getDeptId(){
return deptId;
}
public void setDeptId(int deptId){
this.deptId = deptId;
}
public String getDeptName(){
return deptName;
}
public void setDeptName(String deptName){
this.deptName = deptName;
}
public Set<Employee> getEmps(){
return emps;
}
public void setEmps(Set<Employee> emps){
this.emps = emps;
}
}
- 员工类
public class Employee {
private int empId;
private String empName;
private double salary;
// [多对一]员工与部门
private Dept dept;
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 double getSalary(){
return salary;
}
public void setSalary(double salary){
this.salary = salary;
}
public Dept getDept(){
return dept;
}
public void setDept(Dept dept){
this.dept = dept;
}
}
配置文件设置
- 部门的配置文件
<?xml version="1.0"?>
<!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.flynn.one2many">
<class name="Dept" table="t_dept">
<id name="deptId">
<generator class="native"/>
</id>
<property name="deptName"></property>
<!--
一对多关联映射的配置(通过部门管理到员工)
Dept 映射关键点:
1. 指定 映射的集合属性: "emps"
2. 集合属性对应的集合表: "t_employee"
3. 集合表的外键字段 "t_employee. dept_id"
4. 集合元素的类型
-->
<set name="emps" table="t_employee">
<key column="dept_id"></key>
<one-to-many class="Employee"></one-to-many>
</set>
</class>
</hibernate-mapping>
- 员工的配置文件
<?xml version="1.0"?>
<!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.flynn.one2many">
<class name="Employee" table="t_employee">
<id name="empId">
<generator class="native"/>
</id>
<property name="empName" length="20"></property>
<property name="salary" type="double"></property>
<!--
多对一映射配置
Employee 映射关键点:
1. 映射的部门属性 : dept
2. 映射的部门对象,对应的外键字段: dept_id
3. 部门的类型
-->
<many-to-one name="dept" column="dept_id" class="Dept"></many-to-one>
</class>
</hibernate-mapping>
测试
@Test
public void testSaveDept(){
Session session = sessionFactory.openSession();
session.beginTransaction();
// 部门对象
Dept dept = new Dept();
dept.setDeptName("app developer");
// 员工对象
com.flynn.one2many.Employee emp_zs = new com.flynn.one2many.Employee();
emp_zs.setEmpName("zhangsan");
com.flynn.one2many.Employee emp_ls = new com.flynn.one2many.Employee();
emp_ls.setEmpName("lishi");
// 关系
Set<com.flynn.one2many.Employee> set = new HashSet<>();
set.add(emp_zs);
set.add(emp_ls);
dept.setEmps(set);
// 保存
session.save(emp_zs);
session.save(emp_ls);
session.save(dept); // 保存部门 部门下所有的员工
session.getTransaction().commit();
session.close();
/*
控制台Hibernate的打印:
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
Hibernate: insert into t_employee (empName, salary, dept_id) values (?, ?, ?)
Hibernate: insert into t_dept (deptName) values (?)
Hibernate: update t_employee set deptId=? where empId=?
Hibernate: update t_employee set deptId=? where empId=?
*/
}
// [推荐] 保存, 部员方[多的一方操作]
@Test
public void testSaveEmp(){
Session session = sessionFactory.openSession();
session.beginTransaction();
// 部门对象
Dept dept = new Dept();
dept.setDeptName("java developer");
// 员工对象
com.flynn.one2many.Employee emp_zs = new com.flynn.one2many.Employee();
emp_zs.setEmpName("zhangsan");
com.flynn.one2many.Employee emp_ls = new com.flynn.one2many.Employee();
emp_ls.setEmpName("lishi");
// 关系
emp_zs.setDept(dept);
emp_ls.setDept(dept);
// 保存
session.save(dept); // 先保存一的方法
session.save(emp_zs);
session.save(emp_ls); // 再保存多的一方, 关系会自动维护(映射配置完)
session.getTransaction().commit();
session.close();
/*
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 (?, ?, ?)
*/
}
/**
* 获取数据
*/
@Test
public void testDeptOrEmp(){
Session session = sessionFactory.openSession();
session.beginTransaction();
// 1.通过部门方, 获取另外一方
Dept dept = (Dept) session.get(Dept.class, 1);
System.out.println(dept.getDeptName());
System.out.println(dept.getEmps()); // 懒加载
// 2.通过员工方, 获取另外一方
com.flynn.one2many.Employee employee = (com.flynn.one2many.Employee) session.get(com.flynn.one2many.Employee.class, 1);
System.out.println(employee.getEmpName());
System.out.println(employee.getDept());
}
在一对多与多对一的关联关系中, 保存数据最好的通过多的一方来维护关系, 这样可以减少update语句的生成, 从而提高 hibernate 的执行效率 !
配置一对多与多对一 , 这种叫"双向关联"
只配置一对多 , 叫"单项一对多"
只配置多对一, 叫"单项多对一"
注意:
- 配置了哪一方, 哪一方才有维护关联关系的权限!
Inverse属性
Inverse属性,是在维护关联关系的时候起作用的。
表示控制权是否转移。(在一的一方起作用)
Inverse , 控制反转。
Inverse = false 不反转; 当前方有控制权
True 控制反转; 当前方没有控制权
维护关联关系中,是否设置inverse属性:
- 保存数据
有影响。
如果设置控制反转,即inverse=true, 然后通过部门方维护关联关系。在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护。即外键字段为NULL
image.png
- 保存数据
- 获取数据
无。
- 获取数据
-
- 解除关联关系?
有影响。
- inverse=false, 可以解除关联
- inverse=true, 当前方(部门)没有控制权,不能解除关联关系 (不会生成update语句,也不会报错)
- 解除关联关系?
-
- 删除数据对关联关系的影响?
有影响。
- inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。
- inverse=true, 没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束! 如果删除的记录没有被引用,可以直接删除。
- 删除数据对关联关系的影响?
cascade 属性
cascade 表示级联操作 【可以设置到一的一方或多的一方】
- none 不级联操作, 默认值
- save-update 级联保存或更新
- delete 级联删除
- save-update,delete 级联保存、更新、删除
- all 同上。级联保存、更新、删除
网友评论