学习目标:
1、了解hibernate一对多的配置和使用
学习过程:
一、一对多关系的配置
我们知道在数据库设计时,数据库表之间有有关系的,包括一对多、一对一和多对多,今天我们就主要学习hibernate对是如何支持这样这些关系,如何映射到我们的javaBean中的。为了更好的讲解这方面的内容,我们先设计一下场景:
一个员工只能有一个职位,一个职位就有多个员工。 一对多
一个员工只有有一个登陆账号,一个登陆账号只能属于一个员工。 一对一
一个账号可以有多个角色,一个角色也可以分配给多个账号。 多对多
根据上面的场景我们设计数据库如下:
虽然我们昨天讲过如何通过MyEclipse的反转工具生成javaBean和映射文件,不过这里为了让大家有一个更好的了解,所以我们还是手动的写javaBean和映射文件。
一、一对多的配置
这里我们先讲讲如何配置一对多和多对一的关系,
1、多对一
(1)javaBean的属性
对于多对一的关系,我们只需要在多方配置一个一方的对象就可以了。比如上面的例子,员工和职位的关系就是一个多对一的关系,在pojo中如何表示这个关系呢?只需要在员工表中定义一个职位对象就可以了,代码如下:
public class Employee implements java.io.Serializable {
private Integer employeeId;
private Post post;// 多对一
private String employeeName;
public Post getPost() {
return post;
}
public void setPost(Post post) {
this.post = post;
}
public Integer getEmployeeId() {
return this.employeeId;
}
public void setEmployeeId(Integer employeeId) {
this.employeeId = employeeId;
}
public String getEmployeeName() {
return this.employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
}
(2)映射文件的配置。
然后映射文件,hibernate专门提供了一个标签就是many-to-one,表示这种多对一的关系。修改employee的映射文件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>
<class name="com.javadayup.stuormrelate.Employee" table="employee" catalog="hbm_db">
<id name="employeeId" type="java.lang.Integer">
<column name="employee_id" />
<generator class="native" />
</id>
<property name="employeeName" type="java.lang.String">
<column name="employee_name" length="200" />
</property>
<many-to-one name="post" class="com.javadayup.stuormrelate.Post" >
<column name="post_id"></column>
</many-to-one>
</class>
</hibernate-mapping>
这样我们就完成了配置了。
2、一对多
我们把角色换一下,职位表和员工表就是一对多的关系,那么一方(也就是主表),如何表示对多方的关系呢?
(1)修改pojo属性,为了表示多方,我们需要集合类,hibernate建立我们使用set集合,为了防止空指针,最好定义的时候就构造这个集合对象。修改Post代码如下:
public class Post implements java.io.Serializable {
private Integer postId;
private String postName;
//一对多 List map set
private Set<Employee> employees=new HashSet<Employee>();
public Set<Employee> getEmployees() {
return employees;
}
public void setEmployees(Set<Employee> employees) {
this.employees = employees;
}
public Integer getPostId() {
return this.postId;
}
public void setPostId(Integer postId) {
this.postId = postId;
}
public String getPostName() {
return this.postName;
}
public void setPostName(String postName) {
this.postName = postName;
}
}
(2)映射文件hibernate专门提供了set属性Post.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>
<class name="com.javadayup.stuormrelate.Post" table="post" catalog="hbm_db">
<id name="postId" type="java.lang.Integer">
<column name="post_id" />
<generator class="native" />
</id>
<property name="postName" type="java.lang.String">
<column name="post_name" length="200" />
</property>
<!-- 一对多 -->
<set name="employees" cascade="all">
<key>
<column name="post_id"></column>
</key>
<one-to-many class="com.javadayup.stuormrelate.Employee" />
</set>
</class>
</hibernate-mapping>
好这样我们就完成了配置了。这样配置有什么好处呢?在第四节课的时候我们会讲解如何利用这些关系完成级联更新和查询操作,hibernate提供了非常简单的方式就可以完成这些功能了。
二、级联操作
这样配置了之后又什么好处呢?好处是非常多的,我们以后慢慢介绍,先说说第一个好处,就是可以级联操作,我们可以在内存中把对象之间的关系先建立好,然后映射到数据库中,hibernate会自动级联进行操作。比如上面的例子,我们可以修改一对多或者多对一的配置,添加cascade属性,实现级联操作。
cascade属性可以级联删除和级联更新: hibernate比数据库的外键的级联删除更新强大很多,我们完全可以使用面向对象的方式去操作数据库,hibernate会智能的生成对应的数据库语句。
值 save-update :表示当保存和更新当前对象(即insert和update语句时),会级联保存和更新与他关联的对象
值 all :表示任何情况下都会进行级联操作,即对一个对象进行操作,也会对和他关联的其他对象进行同样的操作
值 delete :表示在执行delete时,进行级联操作,删除和他关联的对象
值 none :表示任何情况下,都不会进行级联操作
比如修改Employee.hbm.xml代码如下:
<many-to-one name="post" class="com.pojo.Post" cascade="save-update">
<column name="post_id"></column>
</many-to-one>
写一个测试类,可以在添加员工的同时级联添加账号信息。代码如下:
public class Run {
public static void main(String[] args) {
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
// 现在在内存
Employee employee = new Employee();
employee.setEmployeeName("刘德华");
Post post = new Post();
post.setPostName("程序员");
Set<Employee> employees=new HashSet<Employee>();
employees.add(employee);
post.setEmployees(employees);
// 开启一个事务
session.beginTransaction();
// 操作数据库 直接操作对象 持久化
session.save(post);
// 提交事物
session.getTransaction().commit();
}
}
虽然感觉我们也只是保存post信息,但是因为员工信息和职位信息已经建立了关系,所以我们查看输出的sql却输出了很多sql,再打开数据库查看是否员工信息和职位信息表都插入了数据,并且关系也建立了。hibernate就是这么神奇。
Hibernate: insert into hbm_db.post (post_name) values (?)
Hibernate: insert into hbm_db.employee (employee_name, post_id) values (?, ?)
Hibernate: update hbm_db.employee set post_id=? where employee_id=?