关联关系:
一对多(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。
当然不告诉部门所属的员工,执行也是成功的