Hibernate学习笔记8--关联关系之一对多

关联关系:

一对多(Department-Employee)

 

前言:

从部门的角度来考虑这个问题,就是一对多了~,一个部门对多个员工。
一、类中实现一对多的关联:在Department创建一个Employee的集合
关系模型:主外键,和上一章一样没什么变化。

Department类代码如下:在Department创建一个Employee的集合

package cn.itcast.domain;

import java.util.Set;
/**
 * 部门类
 * @author Mars
 *
 */
public class Department {
 
 private int id;
 private String name;
 private Set<Employee>emps;
 public int getId() {
  return id;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Set<Employee> getEmps() {
  return emps;
 }
 public void setEmps(Set<Employee> emps) {
  this.emps = emps;
 }
}


Employee类代码如下:没有变化

package cn.itcast.domain;
/**
 * 员工类
 * 
 * @author Mars
 *
 */
public class Employee {
 private int id;
 private String name;
 private Department depart;
 public int getId() {
  return id;
 }
 public Department getDepart() {
  return depart;
 }
 public void setDepart(Department depart) {
  this.depart = depart;
 }
 public void setId(int id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
}


精华都在Department.hbm.xml:添加<set></set>节点

 

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.domain">
	<class name="Department" >
		<!-- 对象标示符,类型可以不写,hibernate自己识别 -->
		<id name="id" column="id">
			<!-- 指定主键生成方式。
        native根据方言判定生成主键的方式
         -->
			 <generator class="native"/> 
		</id>
		
		<property name="name" column="name" unique="true" not-null="true"/><!--标示name唯一性,非空的限制 -->
		<set name="emps" >
		<key column="depart_id"></key><!-- 告诉hibernate按照什么字段检索employee表数据,必须和employee.hbm.xnml中的外键定义一样 -->
		<one-to-many class="Employee"></one-to-many><!-- 告诉hibernate集合set中装什么类型 -->
		</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://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cn.itcast.domain">
	<class name="Employee">
		<!-- 对象标示符,类型可以不写,hibernate自己识别 -->
		<id name="id" column="id">
			<!-- 指定主键生成方式。
        native根据方言判定生成主键的方式
         -->
			 <generator class="native"/> 
		</id>
		
		<property name="name" column="name" unique="true" not-null="true"/><!--标示name唯一性,非空的限制 -->
		<!-- private Department depart是一个复杂的属性,所以不能用 property映射-->
		<!--Employee类中Department的对象名  -->
		<many-to-one name="depart" column="depart_id" not-null="true" ></many-to-one>
	</class>
	

</hibernate-mapping>

测试类:

package cn.itcast.RelationalMapping;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;

import cn.itcast.dao.HibernateUtil;
import cn.itcast.domain.Department;
import cn.itcast.domain.Employee;

/**
 * 一对多测试类
 * @author Mars
 *
 */
public class One2many {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		//Department dept = add();
		Department dept = add2();
		queryDepart(dept.getId());
	}
	/**
	 * 一对多查询方法
	 * @param empId
	 * @return
	 */
	static Department queryDepart(int deptId){
		Session s = null;
		Transaction tx =null;
		try {
			s=HibernateUtil.getSession();
			tx=s.beginTransaction();
			Department depart = (Department)s.get(Department.class, deptId);
			// 分两步:1,根据departid查询部门的相关数据
			//         2.根据departid查询相应的employee相关数据
			System.out.println("emp size:"+depart.getEmps().size());
			//涉及懒加载先这么写吧
			Hibernate.initialize(depart.getEmps());
			tx.commit();
			return depart;
		} finally{
			if(s!=null){
				s.close();
			}
		}
	}
	/**
	 * 一对多添加方法
	 * 告诉用户所从属的部门
	 * @return
	 */
	static Department add(){
		Session s = null;
		Transaction tx =null;
		
		try {
			Department depart = new Department();
			depart.setName("depart name");
			//告诉用户所从属的部门
			Employee  emp1 = new Employee();
			emp1.setDepart(depart);//对象模型,建立两个对象的关联
			emp1.setName("emp name1");
			
			Employee  emp2 = new Employee();
			emp2.setDepart(depart);//对象模型,建立两个对象的关联
			emp2.setName("emp name2");
			s=HibernateUtil.getSession();
			tx=s.beginTransaction();
			s.save(depart);
			s.save(emp1);
			s.save(emp2);
			tx.commit();
			return depart;
		} finally{
			if(s!=null){
				s.close();
			}
		}
	}
	
}



执行的步骤分析如下:

通过sql就能看出hibernate的实现过程:
Hibernate:
    insert
    into
        Department
        (name, id)
    values
        (?, ?)
Hibernate:
    insert
    into
        Employee
        (name, depart_id, id)
    values
        (?, ?, ?)
Hibernate:
    insert
    into
        Employee
        (name, depart_id, id)
    values
        (?, ?, ?)
Hibernate:
    select
        department0_.id as id1_0_0_,
        department0_.name as name2_0_0_
    from
        Department department0_
    where
        department0_.id=?
Hibernate:
    select
        emps0_.depart_id as depart3_0_1_,
        emps0_.id as id1_1_1_,
        emps0_.id as id1_1_0_,
        emps0_.name as name2_1_0_,
        emps0_.depart_id as depart3_1_0_
    from
        Employee emps0_
    where
        emps0_.depart_id=?
emp size:2
// 分两步:1,根据departid查询部门的相关数据
//         2.根据departid查询相应的employee相关数据

二、对于告诉部门所从属的员工

后续添加一个告诉部门所从属的员工的添加方法

/**
	 * 一对多添加方法
	 * 告诉用户所从属的部门及告诉部门所从属的员工
	 * @return
	 */
	static Department add2(){
		Session s = null;
		Transaction tx =null;
		
		try {
			Department depart = new Department();
			depart.setName("depart name");
			//告诉用户所从属的部门
			Employee  emp1 = new Employee();
			emp1.setDepart(depart);//对象模型,建立两个对象的关联
			emp1.setName("emp name1");
			
			Employee  emp2 = new Employee();
			emp2.setDepart(depart);//对象模型,建立两个对象的关联
			emp2.setName("emp name2");
			
			//告诉部门所从属的员工
			Set<Employee>emps = new HashSet<Employee>();
			emps.add(emp1);
			emps.add(emp2);
			depart.setEmps(emps);
			
			s=HibernateUtil.getSession();
			tx=s.beginTransaction();
			s.save(depart);
			s.save(emp1);
			s.save(emp2);
			tx.commit();
			return depart;
		} finally{
			if(s!=null){
				s.close();
			}
		}
	}

分析:通过sql可以看出多了几条update语句

insert
    into
        Department
        (name, id)
    values
        (?, ?)
Hibernate:
    insert
    into
        Employee
        (name, depart_id, id)
    values
        (?, ?, ?)
Hibernate:
    insert
    into
        Employee
        (name, depart_id, id)
    values
        (?, ?, ?)
Hibernate:
    update
        Employee
    set
        depart_id=?
    where
        id=?
Hibernate:
    update
        Employee
    set
        depart_id=?
    where
        id=?
Hibernate:
    select
        department0_.id as id1_0_0_,
        department0_.name as name2_0_0_
    from
        Department department0_
    where
        department0_.id=?
Hibernate:
    select
        emps0_.depart_id as depart3_0_1_,
        emps0_.id as id1_1_1_,
        emps0_.id as id1_1_0_,
        emps0_.name as name2_1_0_,
        emps0_.depart_id as depart3_1_0_
    from
        Employee emps0_
    where
        emps0_.depart_id=?
emp size:2


对于一对多和多对一,其实本质就是一个外键的更新,当然后续会讲到级联是会讲到如何去掉这两条update。
当然不告诉部门所属的员工,执行也是成功的

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值