Hibernate之一对多与多对一映射

来源:互联网 发布:淘宝门头制作 编辑:程序博客网 时间:2024/04/29 19:02

一,概述

需求:员工与部门,一个部门有多个员工,多个员工可以在同一个部门,这是典型的一对多与多对一关系.这种关系在Hibernate中怎样映射呢?(Hibernate中这种映射叫关联映射)

二,设计JavaBean

1)部门

package com.bighuan.b_one2many;import java.util.HashSet;import java.util.Set;public class Dept {    private int deptId;    private String deptName;    /**     * 一对多,一个部门对应多个员工     */    private Set<Employee> emps=new HashSet<Employee>();        public Dept(){            }        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;    }   }

2)员工

package com.bighuan.b_one2many;public class Employee {private int empId;private String empName;private double salary;/** * 多对一:多个员工对应一个部门 */private Dept dept;public Employee(){}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;}}

三,JavaBean对应的映射文件

1)Dept.hbm.xml

<?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.bighuan.b_one2many"><!-- 对象与表对应 --><class name="Dept" table="t_dept"><!-- 属性与字段对应 --><!-- 主键 ,映射--><id name="deptId"><generator class="native" /></id><!-- 属性映射 --><property name="deptName" length="20"></property><!-- 一对多关联映射配置  (通过部门管理到员工)Dept 映射关键点:1.  指定 映射的集合属性: "emps"2.  集合属性对应的集合表: "t_employee"3.  集合表的外键字段   "t_employee. dept_id"4.  集合元素的类型dept_id需要和Employ.hbm.xml中<many-to-one>中的column一样 --><set name="emps" table="t_employee"><!-- table="t_employee" 可以省略 --><key column="dept_id"></key><one-to-many class="Employee"/></set></class></hibernate-mapping>

2)Employee.hbm.xml

<?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.bighuan.b_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.  映射的部门属性  :  dept2.  映射的部门属性,对应的外键字段: dept_id3.  部门的类型many-to-one可以做到将一个对象映射生成一个外键字段 --> <many-to-one name="dept" column="dept_id" class="Dept"></many-to-one></class></hibernate-mapping>
(hibernate.cfg.xml在前面几篇关于Hibernate的博客里都有介绍,不粘贴了)

四,测试

1)插入数据

package com.bighuan.b_one2many;import java.util.HashSet;import java.util.Set;import org.hibernate.SessionFactory;import org.hibernate.cfg.Configuration;import org.junit.Test;import com.bighuan.a_collection.User;public class App {private static SessionFactory sf;static {sf = new Configuration().configure().addClass(Dept.class).addClass(Employee.class)//测试时用.buildSessionFactory();}//保存:部门方,一的一方进行操作@Testpublic void testSave() throws Exception {// 获得sessionorg.hibernate.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();}//保存:员工方,多的一方进行操作,推荐使用多的一方进行保存数据@Testpublic void testSave2() throws Exception {// 获得sessionorg.hibernate.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();}}
2)既可以通过部门方来保存数据,也可以通过员工方来保存数据.通过部门方保存数据执行了如下sql语句:

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 dept_id=? where empId=?Hibernate: update t_employee set dept_id=? where empId=?
而通过员工方保存数据则执行了更少的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 (?, ?, ?)
通过对比可以得知,通过多的一方来保存数据可以减少update语句,因此开发中建议通过多的一方来保存数据,减少sql语句的执行,提高Hibernate效率.

五,inverse与cascade属性

1)Inverse属性,是在维护关联关系的时候起作用的, 表示控制权是否转移。(在一的一方起作用)
Inverse , 控制反转;Inverse = false  不反转;当前方有控制权;inverse= true 控制反转,当前方没有控制权.
2)维护关联关系中,是否设置inverse属性:
a. 保存数据
有影响。
如果设置控制反转,即inverse=true, 然后通过部门方维护关联关系。在保存部门的时候,同时保存员工, 数据会保存,但关联关系不会维护。即外键字段为NULL.
b. 获取数据

无影响.
c. 解除关联关系?
有影响。
 inverse=false,可以解除关联;inverse=true,前方(部门)没有控制权,不能解除关联关系(不会生成update语句,也不会报错).
d. 删除数据对关联关系的影响?
有影响。
inverse=false, 有控制权, 可以删除。先清空外键引用,再删除数据。
inverse=true,  没有控制权: 如果删除的记录有被外键引用,会报错,违反主外键引用约束!  如果删除的记录没有被引用,可以直接删除。
3)cascade 属性
cascade  表示级联操作  【可以设置到一的一方或多的一方】
    none          不级联操作, 默认值
    save-update     级联保存或更新
    delete          级联删除
    save-update,delete    级联保存、更新、删除
    all   同上。级联保存、更新、删除

六,总结

配置一对多与多对一,这种叫“双向关联”;只配置一对多,叫“单项一对多”;只配置多对一, 叫“单项多对一”.
注意:配置了哪一方,哪一方才有维护关联关系的权限!







0 0
原创粉丝点击