逸品汽车网
您的当前位置:首页Hibernate关联映射

Hibernate关联映射

来源:逸品汽车网


集合映射 开发流程: 需求分析/数据库设计、项目设计/ 编码/测试/实施部署上线/验收需求: 用户购买, 填写地址! // javabean设计 public class User { private int userId; private String userName; // 一个用户,对应的多个地址 private Set String addre

集合映射

开发流程:
 需求分析/数据库设计、项目设计/ 编码/测试/实施部署上线/验收

需求:
 用户购买, 填写地址!
// javabean设计
public class User {

 private int userId;
 private String userName;
 // 一个用户,对应的多个地址
 private Set address;
 private List addressList = new ArrayList(); 
 //private String[] addressArray; // 映射方式和list一样 
 private Map addressMap = new HashMap();

}






 
 
 
  
 

 
 
 
 
 

 
 
 
 
 
 

 
 
 
 
 
  
 
 // 测试程序
 // 保存set
 @Test
 public void testSaveSet() throws Exception {
 Session session = sf.openSession();
 session.beginTransaction();

 //-- 保存
 Set addressSet = new HashSet();
 addressSet.add("广州");
 addressSet.add("深圳");
 // 用户对象
 User user = new User();
 user.setUserName("Jack");
 user.setAddress(addressSet);

 // 保存
 session.save(user);

 session.getTransaction().commit();
 session.close();
 }

 // 保存list/map
 @Test
 public void testSaveList() throws Exception {
 Session session = sf.openSession();
 session.beginTransaction();
 User user = new User();
 user.setUserName("Tom");
// // 用户对象 -- list
// user.getAddressList().add("广州");
// user.getAddressList().add("深圳");
// // 保存
// session.save(user);

 // 用户对象 -- Map
 user.getAddressMap().put("A0001", "广州");
 user.getAddressMap().put("A0002", "深圳");

 // 保存
 session.save(user);

 session.getTransaction().commit();
 session.close();
 }
问题:
 集合映射,映射的集合元素,都是普通的类型, 能否为对象类型?

关联映射

需求1:
 部门与员工
 一个部门有多个员工; 【一对多】
 多个员工,属于一个部门 【多对一】
需求2:
 项目与开发员工
 一个项目,有多个开发人员!
 一个开发人员,参与多个项目! 【多对多】

多对一映射与一对多

1. 需求:员工与部门
2. 数据库:
3. 设计javabean封装:
4. 映射:

JavaBean

public class Dept {

 private int deptId;
 private String deptName;
 // 【一对多】 部门对应的多个员工
 private Set emps = new HashSet();
} 
public class Employee {

 private int empId;
 private String empName;
 private double salary;
 // 【多对一】员工与部门
 private Dept dept;
}

Dept.hbm.xml






 
 
 
  
 

 
  
 
 
  
 

Employee.hbm.xml






 
 
 
  
 
 

 
  
 

测试


public class App {

 private static SessionFactory sf;
 static {
 sf = new Configuration()
 .configure()
 .addClass(Dept.class) 
 .addClass(Employee.class) // 测试时候使用
 .buildSessionFactory();
 }

 // 保存, 部门方 【一的一方法操作】
 @Test
 public void save() {

 Session session = sf.openSession();
 session.beginTransaction();

 // 部门对象
 Dept dept = new Dept();
 dept.setDeptName("应用开发部");
 // 员工对象
 Employee emp_zs = new Employee();
 emp_zs.setEmpName("张三");
 Employee emp_ls = new Employee();
 emp_ls.setEmpName("李四");
 // 关系
 dept.getEmps().add(emp_zs);
 dept.getEmps().add(emp_ls);

 // 保存
 session.save(emp_zs);
 session.save(emp_ls);
 session.save(dept); // 保存部门,部门下所有的员工 

 session.getTransaction().commit();
 session.close();
 /*
 * 结果
 * 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=? 维护员工引用的部门的id
 Hibernate: update t_employee set deptId=? where empId=?
 */
 }
 // 【推荐】 保存, 部员方 【多的一方法操作】
 @Test
 public void save2() {

 Session session = sf.openSession();
 session.beginTransaction();

 // 部门对象
 Dept dept = new Dept();
 dept.setDeptName("综合部");
 // 员工对象
 Employee emp_zs = new Employee();
 emp_zs.setEmpName("张三");
 Employee emp_ls = new Employee();
 emp_ls.setEmpName("李四");
 // 关系
 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 (?, ?, ?)
 少生成2条update sql
 */
 }
}

总结

 在一对多与多对一的关联关系中,保存数据最好的通过多的一方来维护关系,这样可以减少update语句的生成,从而提高hibernate的执行效率!

配置一对多与多对一,这种叫“双向关联”
只配置一对多, 叫“单项一对多”
只配置多对一, 叫“单项多对一”

注意:
 配置了哪一方,哪一方才有维护关联关系的权限!

Inverse属性

Inverse属性,是在维护关联关系的时候起作用的。
 表示控制权是否转移。(在一的一方起作用)

Inverse , 控制反转。
Inverse = false 不反转; 当前方有控制权
 True 控制反转; 当前方没有控制权

维护关联关系中,是否设置inverse属性:

 1. 保存数据 
 有影响。
 如果设置控制反转,即inverse=true, 然后通过部门方维护关联关系。在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护。即外键字段为NULL

 2. 获取数据
 无。
 3. 解除关联关系?
 有影响。
 inverse=false, 可以解除关联
 inverse=true, 当前方(部门)没有控制权,不能解除关联关系
 (不会生成update语句,也不会报错)
 4. 删除数据对关联关系的影响?
 有影响。
 inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。
 inverse=true, 没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束! 如果删除的记录没有被引用,可以直接删除。

cascade 属性

cascade 表示级联操作 【可以设置到一的一方或多的一方】
 none 不级联操作, 默认值
 save-update 级联保存或更新
 delete 级联删除
 save-update,delete 级联保存、更新、删除
 all 同上。级联保存、更新、删除

多对多映射

需求:项目与开发人员
 Project Developer
 电商系统
 曹吉
 王春
 OA系统
 王春
 老张

JavaBean

public class Developer {
 private int d_id;
 private String d_name;
 // 开发人员,参数的多个项目
 private Set projects = new HashSet();
}
public class Project {
 private int prj_id;
 private String prj_name;
 // 项目下的多个员工
 private Set developers = new HashSet();
}

Project.hbm.xml






 
 
 
  
 
 
 
 
 
  
 

Developer.hbm.xml






 
 
 
  
 

 
 
 
 
  
 

维护关联关系

设置inverse属性,在多对多种维护关联关系的影响?

1) 保存数据
 有影响。
 inverse=false ,有控制权,可以维护关联关系; 保存数据的时候会把对象关系插入中间表;
 inverse=true, 没有控制权, 不会往中间表插入数据。

2) 获取数据
 无。

3) 解除关系
 有影响。
 inverse=false ,有控制权, 解除关系就是删除中间表的数据。
 inverse=true, 没有控制权,不能解除关系。

4) 删除数据
 有影响。
 inverse=false, 有控制权。 先删除中间表数据,再删除自身。
 inverse=true, 没有控制权。 如果删除的数据有被引用,会报错! 否则,才可以删除
显示全文