Hibernate之一对多与多对一映射

一,概述

需求:员工与部门,一个部门有多个员工,多个员工可以在同一个部门,这是典型的一对多与多对一关系.这种关系在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.  映射的部门属性  :  dept
			2.  映射的部门属性,对应的外键字段: dept_id
			3.  部门的类型
			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();
	}

	//保存:部门方,一的一方进行操作
	@Test
	public void testSave() throws Exception {
		// 获得session
		org.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();
	
	}
	
	//保存:员工方,多的一方进行操作,推荐使用多的一方进行保存数据
	@Test
	public void testSave2() throws Exception {
		// 获得session
		org.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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值