部门代码 Department.java:
package com.cn.domain;
import java.util.HashSet;
import java.util.Set;
public class Department {
private Integer id;
private String name;
private Set<Employee> emps = new HashSet<Employee>();
public Set<Employee> getEmps() {
return emps;
}
public void setEmps(Set<Employee> emps) {
this.emps = emps;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
员工代码 Employee.java:
package com.cn.domain;
public class Employee {
private Integer id;
private String userName;
private Department depart;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public Department getDepart() {
return depart;
}
public void setDepart(Department depart) {
this.depart = depart;
}
}
Employee.hbm.xml映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.cn.domain">
<class name="Employee" table="employee">
<id name="id">
<column name="id"/>
<generator class="native"/>
</id>
<property name="userName"/>
<many-to-one name="depart" column="depart_id"/>
</class>
</hibernate-mapping>
Depart.hbm.xml映射文件:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping
package="com.cn.domain">
<class name="Department" table="department">
<id name="id">
<column name="id"/>
<generator class="native"></generator>
</id>
<property name="name"/>
<set name="emps">
<key>
<column name="depart_id"></column>
</key>
<one-to-many class="Employee"/>
</set>
</class>
</hibernate-mapping>
HibernateDepartmentDAO.java文件:
package com.cn.dao;
import java.util.HashSet;
import java.util.Set;
import org.hibernate.Session;
import org.hibernate.Transaction;
import com.cn.domain.Department;
import com.cn.domain.Employee;
import com.cn.session.HibernateSessionUtils;
public class HibernateDepartmentDAO {
public static void main(String[] args){
add();
}
public static Department add(){
Session session = HibernateSessionUtils.getSession();
Transaction trans = session.beginTransaction();
Set<Employee> emps = new HashSet<Employee>();
Department depart = new Department();
depart.setName("财务部");
Employee emp1 = new Employee();
emp1.setUserName("wgz");
//告知部员工一他属于哪个部门
emp1.setDepart(depart);
Employee emp2 = new Employee();
emp2.setUserName("cdx");
//告知部员工二他属于哪个部门
emp2.setDepart(depart);
emps.add(emp1);
emps.add(emp2);
//告知部门它有哪些员工
depart.setEmps(emps);
//保存员工一信息
session.save(emp1);
//保存员工二信息
session.save(emp2);
//保存部门信息
session.save(depart);
trans.commit();
HibernateSessionUtils.close();
return null;
}
}
注意:本例映射文件没有配级联和inverse
emps.add(emp1);
emps.add(emp2);
session.save(depart);
先保存的是部门员工信息,后保存的是部门信息,下面来看下结果输出地sql语句:
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into department (name) values (?)
Hibernate: update employee set userName=?, depart_id=? where id=?
Hibernate: update employee set userName=?, depart_id=? where id=?
Hibernate: update employee set depart_id=? where id=?
Hibernate: update employee set depart_id=? where id=?
其中的
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into department (name) values (?)
很好理解,他是有下面语句产生的:
session.save(emp1);
session.save(emp2);
session.save(depart);
但是下面这是条更新语句是怎么回事呢?这两天想了好久还是有点不太明白,最后联系现实生活的例子,勉强给下面的解释,不知得不对,反正我这样理解:
如果我把这两条给注解掉
emp1.setDepart(depart);
emp2.setDepart(depart);
输出的sql语句是:
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into department (name) values (?)
Hibernate: update employee set depart_id=? where id=?
Hibernate: update employee set depart_id=? where id=?
可以发现
Hibernate: update employee set userName=?, depart_id=? where id=?
Hibernate: update employee set userName=?, depart_id=? where id=?
这两条更新语句不见了,由此可以推段导致上面两句update语句不见是emp1.setDepart(depart);
emp2.setDepart(depart);
这两句被注解掉的原因,下面来分析一下什么原因:
当执行到这句话emp2.setDepart(depart);已经建立了部门与员工表之间的关联。但执行session.save(emp1);这就话时员工以还不知道他是那个部门,同样执行session.save(emp1);时员工与不知他在哪个部门,所以在持久化时depart_id还是空的。打个比方:当一个公司招聘了两个员工,但是没给他分配他隶属在哪个部门(假设这个部门公司还没有打算建立该部门,先招员工),当员工招进公司后,他当然应该有一个自己员工编号的属性 (id),名字的属性(userName),理所当然也应该有个隶属那个部门的部门编号(depart_id),但是员工不知道自己在那个部门,当然部门也没通知员工在那个部门。这是保存在数据库中的的employee表中的depat_id应该是null的了。当执行session.save(depart);语句时,这时部门已经建好了,他通知那些员工隶属这个部门,同时通知员工更新员工更新自己档案袋里的depart_id的信息。所以会产生
Hibernate: update employee set userName=?, depart_id=? where id=?
Hibernate: update employee set userName=?, depart_id=? where id=?
这两个更新语句
这是我把
emp1.setDepart(depart);
emp2.setDepart(depart);
这两句注解给去掉,输出地sql语句是:
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into employee (userName, depart_id) values (?, ?)
Hibernate: insert into department (name) values (?)
Hibernate: update employee set userName=?, depart_id=? where id=?
Hibernate: update employee set userName=?, depart_id=? where id=?
Hibernate: update employee set depart_id=? where id=?
Hibernate: update employee set depart_id=? where id=?
下面来分析一下原因:
这里还是假设:公司部门在招进员工时正在组建部门。
当员工招进公司后,他当然应该有一个自己员工编号的属性 (id),名字的属性(userName),理所当然也应该有个隶属那个部门的部门编号(depart_id),由于不知道自己部门的编号,所以档案中的depart_id就写成null了,这时员工进公司也被告知他在哪个部门部门也知道它有哪些员工,但是部门经理说了由于我们部门刚建立公司还没给我们部门分配部门编号,你们档案的depart_暂时先更新为null吧,(于是
Hibernate: update employee set userName=?, depart_id=? where id=?
Hibernate: update employee set userName=?, depart_id=? where id=?
这两条更新语句便产生了)
等以后公司给我们部门分配部门编号后,我通知你们部门编号是什么,那时你们再把你们的depart_id信息给更新,当执行session.save(depart);这个语句是部门已经建立了,公司也给分配了部门的编号,部门经理这时候通知该部门所有员工:“公司现在由部门编号了,你们可以更新你们档案里的depart_id信息了”,于是便有了
Hibernate: update employee set depart_id=? where id=?
Hibernate: update employee set depart_id=? where id=?
这两条update语句
写完后,感觉自己理解的好牵强,希望哪位大侠看到后给指证下
inverse常用于一对多双向关联关系中。
以Student(学生)和Class(班级)为例,它们之间的关系为一对多的关系,即一个学生只能属于一个班级,一个班级可以包含多个学
生。
学生类定义代码:
Class Student{
private int id;
private String name;
private Class class;
//省略getter()和setter()方法
}
班级类定义代码:
Class Class{
private int id;
private String name;
private Set students = new HashSet();
//省略getter()和setter()方法
}
Student类的映射文件:
<class name="Student" table="STUDENT">
<id name="id" type="int" column="ID">
<generator class="native" />
</id>
<property name="name" type="string" column="NAME" />
<many-to-one name="class" column="CLASS_ID" class="Class" cascade="save-update" />
</class>
Class类的映射文件:
<class name="Class" table="CLASS">
<id name="id" type="int" column="ID">
<generator class="native" />
</id>
<property name="name" type="string" column="NAME" />
<set name="students" table="STUDENT" cascade="save-update" inverse="false">
<key column="CLASS_ID" />
<one-to-many class="Student" />
</set>
</class>
希望你能对这两个映射文件所表达的数据库模式有正确的认识。即STUDENT表中存在一个名为CLASS_ID的字段,它和CLASS表中的ID字段是主外键关系。那个inverse属性就是用来规定是由谁(Student或Class)来维护这个主外键关系的。
inverse的默认值为false。
在处理逻辑代码中,如下:
Class c1 = new Class();
c1.setName("一班");
Student s1 = new Student();
Student s2 = new Student();
s1.setName("Jason");
s2.setName("Tom");
c1.getStudents().add(s1);
c2.getStudents().add(s2);
s1.setClass(c1);
s2.setClass(c1); //注释1
session.save(c1);
上面的代码会使Hibernate执行五条SQL语句,其中前三条是insert插入语句,后两条是update更新语句。插入就不用说了,那么为什么还要有更新语句呢?这是因为Class类映射文件的<set>元素中指定了inverse="false",这就告之Hibernate:STUDENT表与CLASS表的主外键关系是由Class类来维护的。当执行save后,执行了三条insert语句,这三条语句中的后两条是插入到STUDENT表的,它们的CLASS_ID字段是通过s1.getClass().getID()取出的,假如我将上面“注释1”处修改为s2.setClass(c2);(c2是另一个Class对象,可能是持久化对象),这样,主外键关系不就乱了吗。为了保证主外键关系,Hibernate在这种情况下会再执行两条update语句来更改STUDENT表中两个新插入记录的CLASS_ID字段,当然,这时CLASS_ID字段的取值是从c1对象中直接取得,而不再是s1.getClass().getID()方式了。
如果我们将Class类映射文件的<set>元素中的inverse属性修改为true,这就是告诉Hibernate:Class类不维护主外键关系了,这个任务就交给了Student类。于是,我们再执行上面的代码,Hibernate就会只执行三条insert语句,而不会执行任何update语句。因为Hibernate会通过Student类的s1.getClass().getID()和s2.getClass().getID()来确定CLASS_ID字段的值。
故,为了节省数据库资源,省却不必要的update语句,我们一般建议在一对多双向关联关系中,将一方的inverse属性设置为true,即将主外键的关系交由多方来维护。
打个比方:在一个公司中,是老板认识所有的员工容易,还是所有员工认识老板容易?
分享到:
相关推荐
在深入探讨《hibernate笔记.txt》所提及的关键知识点前,我们先来解析一下标题和描述中的核心概念。“自上而下的依赖,单向依赖,层与层之间最好依赖抽象”,这一描述实际上触及了软件架构设计中的关键原则,特别是...
《韩顺平.2011版.hibernate笔记》是一份针对Hibernate框架的详细学习资料,由知名IT讲师韩顺平在2011年编撰而成。Hibernate是Java开发领域中广泛使用的对象关系映射(ORM)框架,它极大地简化了数据库操作,使开发者...
【传智播客 Hibernate 笔记】是一份深入学习 Hibernate ORM 框架的资源集合,包括了 word 笔记、pdf 讲义、源代码以及相关分析图表和 jar 包,旨在帮助开发者全面理解并掌握 Hibernate 的核心概念与实际应用。...
《Hibernate笔记完整版》 在Web开发领域,Hibernate作为三大框架之一,扮演着至关重要的角色。本文将全面介绍Hibernate,包括其数据持久化的概念、优缺点对比,以及Hibernate的核心概念和编程步骤。 对象持久化是...
《韩顺平Hibernate笔记》是一份详尽记录了著名IT讲师韩顺平关于Hibernate框架讲解内容的资料集合。Hibernate作为Java领域中广泛使用的对象关系映射(ORM)框架,极大地简化了数据库操作,使得开发者可以更加专注于...
《韩顺平Hibernate笔记》是一份详尽的关于Hibernate框架的学习资料,由知名IT教育专家韩顺平编撰。Hibernate是Java开发中的一个强大的对象关系映射(ORM)框架,它简化了数据库与Java对象之间的交互,使得开发者可以...
Hibernate 是一个开源的对象关系映射(ORM)框架,它允许Java开发者使用面向对象的方式来操作数据库。这个框架将数据库操作转化为对Java对象的操作,简化了数据持久化的复杂度。以下是对Hibernate的一些关键知识点的...
### 尚学堂Hibernate笔记知识点详解 #### 一、项目初始化与环境搭建 1. **新建项目**:在IDE中创建一个新的Java项目。 2. **构建用户库并添加所需的JAR包**: - 右键点击项目 -> `Build Path` -> `Configure ...
培训期间的hibernate笔记 hibernate笔记 达内培训
hibernate笔记.pdf
总结起来,"韩顺平hibernate笔记及图解"涵盖了Hibernate的基础概念、核心组件、对象关系映射、查询机制、事务管理以及实体间的关系等内容。通过学习这份笔记,开发者能深入理解Hibernate的工作原理和使用技巧,提升...
【Spring+Hibernate笔记】这篇文档主要涵盖了在Web开发中使用Spring和Hibernate的基础知识。首先,我们从Spring的Hello World开始,了解如何配置JSP运行环境。 1.1. 配置JSP运行环境是开发Web应用的第一步。这包括...
【马士兵Hibernate笔记】是一份面向初学者的教程,旨在帮助读者深入了解Hibernate这一持久化框架。Hibernate是一个基于Java的ORM(对象关系映射)工具,它允许开发者将数据库操作转换为面向对象的方式,从而简化了...