文档章节

Hibernate框架基础——cascade属性

Airship
 Airship
发布于 2017/08/21 14:04
字数 1599
阅读 9
收藏 0

我们以部门和员工的关系为例讲解一对多关联关系映射时,删除部门时,如果部门有关联的员工且inverse属性为false,那么由于可以维护关联关系,它就会先把关联的员工的外键列设为null值,再删除自己。但是此刻希望删除部门时,就附带着把该部门下的所有员工都删掉,这时就需要引入cascade属性了。

级联(cascade)

hibernate持久化一个临时对象时,在默认情况下,它不会自动持久化所关联的其他临时对象,而是会抛出TransientObjectException。如果设定many-to-one元素的cascade属性为save-update的话,可实现自动持久化所关联的对象。如:

<many-to-one name="customer" 
        column="CUSTOMER_ID" 
        class="..Customer"
        cascade="save-update"
        not-null="true" />

 

级联指的是当主控方执行操作时,关联对象(被动方)是否同步执行同一操作。

级联风格

每个Hibernate session的基本操作包括persist()、merge()、saveOrUpdate()、delete()、lock()、refresh()、evict()、replicate(),这些操作都有对应的级联风格(cascade style)。这些级联风格(cascade style)风格分别命名为persist、merge、save-update、delete、lock、refresh、evict、replicate。

级联风格 Session中的方法
persist persist()
merge merge()
save-update save()、update()、saveOrUpdate()
delete delete()
lock lock()
refresh refresh()
evict evict()
replicate replicate()

如果你希望一个操作被顺着关联关系级联传播,你必须在映射文件中指出这一点。 
指定级联风格

<one-to-one name="person" cascade="persist" />

 

级联风格(cascade style)是可组合的

<one-to-one name="person" cascade="persist,delete" />

 

你可以使用cascade=”all”来指定全部操作都顺着关联关系级联(cascaded)。默认值是cascade=”none”,即任何操作都不会被级联(cascaded)。 
在对象/关系映射文件中,用于映射持久化类之间关联关系的元素,如<set><many-to-one><one-to-one>都有一个cascade属性。 
这里写图片描述

案例分析——cascade属性

还是回到开头我们提出的需求,即删除部门时,就附带着把该部门下的所有员工都删掉。要满足这个需求,我们最好新建一个普通Java工程,如Hibernate_Test,然后在cn.itcast.f_hbm_oneToManyb包下新建持久化类——Department.java和Employee.java。 
持久化类——Department.java的代码如下:

/** * 部门 * @author li ayun * */
public class Department {
    private Integer id;
    private String name;

    private Set<Employee> employees = new HashSet<Employee>(); // 关联的很多个员工

    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;
    }


    public Set<Employee> getEmployees() {
        return employees;
    }

    public void setEmployees(Set<Employee> employees) {
        this.employees = employees;
    }

    @Override
    public String toString() {
        return "[Department: id=" + id + ", name=" + name + "]";
    }
}

持久化类——Employee.java的代码如下:

/** * 员工 * @author li ayun * */
public class Employee {
    private Integer id;
    private String name;

    private Department department; // 关联的部门对象

    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;
    }

    public Department getDepartment() {
        return department;
    }

    public void setDepartment(Department department) {
        this.department = department;
    }

    @Override
    public String toString() {
        return "[Employee: id=" + id + ", name=" + name + "]";
    }
}

由于我们先前就分析过各个持久化类在数据库中所对应的表的结构,所以我们很容易就写出各个持久化类相应的映射配置文件了。 
先在cn.itcast.f_hbm_oneToMany包中创建Department类对应的映射配置文件——Department.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="cn.itcast.f_hbm_oneToMany">
    <class name="Department" table="department">
        <id name="id">
            <generator class="native"></generator> 
        </id>
        <property name="name" />
        <!-- employees属性,Set集合,表达的是本类与Employee的一对多的关系 class属性:关联的实体类型 key子元素:对方表中的外键列(多方的哪个表) inverse属性: 默认为false,表示本方维护关联关系。 如果为true,表示本方不维护关联关系。 只是影响是否能设置外键列的值(设成有效值或是null值),对获取信息没有任何影响。 cascade属性: 默认为none,代表不级联。 级联是指操作主对象时,对关联的对象也做相同的操作。 可设为:delete,save-update,all,none,... -->
        <set name="employees" cascade="save-update,delete">
            <key column="departmentId"></key>
            <one-to-many class="Employee"/>
        </set>
    </class>
</hibernate-mapping>

<set>元素中设置cascade=”save-update,delete”,即表示只须保存/修改某部门,该部门下的所有员工都将保存/修改,或者删除部门时,就附带着把该部门下的所有员工都删掉。 
然后也是在该包中创建Employee类对应的映射配置文件——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="cn.itcast.f_hbm_oneToMany">
    <class name="Employee" table="employee">
        <id name="id">
            <generator class="native"></generator> 
        </id>
        <property name="name" type="string" column="name" />

        <!-- department属性,表达的是本类与Department的多对一的关系 class属性:关联的实体类型 column属性:外键列(引用关联对象的表的主键) -->
        <many-to-one name="department" class="Department" column="departmentId"></many-to-one>
    </class>
</hibernate-mapping>

接下来,我们从以下2个方面来编写代码进行测试

  • 保存新数据,并有关联关系。
  • 删除对象,看对关联对象的影响。

所以,我们要在cn.itcast.f_hbm_oneToMany包中编写一个单元测试类——Application.java。

public class Application {
    private static SessionFactory sessionFactory = new Configuration() //
            .configure() //
            .addClass(Department.class) // 添加Hibernate实体类(加载对应的映射文件)
            .addClass(Employee.class) // 添加Hibernate实体类(加载对应的映射文件)
            .buildSessionFactory();

    // 保存,有关联关系
    @Test
    public void testSave() {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // -------------------------------------------

        // 新建对象
        Department department = new Department();
        department.setName("开发部");

        Employee employee1 = new Employee();
        employee1.setName("张三");

        Employee employee2 = new Employee();
        employee2.setName("李四");

        // 关联起来
        employee1.setDepartment(department); // 告诉员工他属于哪个部门
        employee2.setDepartment(department);
        department.getEmployees().add(employee1); // 告诉部门它有两个关联的员工
        department.getEmployees().add(employee2);

        // 保存
        session.save(department); // 保存部门

        // -------------------------------------------
        session.getTransaction().commit();
        session.close();
    }

        // 删除对象,对关联对象的影响
    @Test
    public void testDelete() {
        Session session = sessionFactory.openSession();
        session.beginTransaction();
        // -------------------------------------------

        // 删除部门方(一方)
        Department department = (Department) session.get(Department.class, 1);
        session.delete(department);

        // -------------------------------------------
        session.getTransaction().commit();
        session.close();
    }
}

这样,当保存部门时,会级联保存该部门下的所有员工,或者删除部门时,就会级联删除该部门下的所有员工。我们也可以配置员工级联删除部门,但这样做,在业务上是极不合理的。

总结

一般是多对一和多对多的时候不使用级联,一对一和一对多可以使用级联,这两种情况使用级联比较多,总结来说,这个对象归你控制,你就能够级联,它不归你一个人所有,那你就不要级联。 
还有一点要注意,inverse属性和cascade属性毛关系都没有。

本文转载自:http://blog.csdn.net/yerenyuan_pku/article/details/52760010

共有 人打赏支持
Airship
粉丝 38
博文 896
码字总数 19689
作品 0
南京
高级程序员
私信 提问
hibernate集合映射inverse和cascade详解

1、到底在哪用cascade="..."? cascade属性并不是多对多关系一定要用的,有了它只是让我们在插入或删除对像时更方便一些,只要在cascade的源头上插入或是删除,所有cascade的关系就会被自己...

长平狐
2012/11/12
64
0
【转载】Hibernate3注解

Hibernate3注解 收藏 1、@Entity(name="EntityName") 必须,name为可选,对应数据库中一的个表 2、@Table(name="",catalog="",schema="") 可选,通常和@Entity配合使用,只能标注在实体的class定...

youfen
08/27
0
0
Hibernate Annotation笔记

(1) 简介: 在过去几年里,Hibernate不断发展,几乎成为Java数据库持久性的事实标准。它非常强大、灵活,而且具备了优异的性能。在本文中,我们将了解如何使用Java 5 注释来简化Hibernate代码...

geeksun
2012/05/14
0
0
Hibernate4实战 之 第四部分:关系映射

数据表之间的关系分为三类:一对一、一对多、多对多 一对一数据表(部门表 和 部门主管表) 一对多数据表(部门表 和 部门下的人员表) 多对多数据表(部门表 和 人员表) 根据相互寻找的关系...

jinnianshilongnian
2012/06/29
0
0
MySql和Hibernate中关于cascade的用法

数据库里的cascade的用法,Mysql和Hibernate里面是不相同。 在数据库里,进行增加、修改、删除记录的时候,经常会涉及到父子关系的表。 例如:有省份表和城市表,其中城市表有一个外键provi...

空云万里晴
2012/08/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

React和Redux的连接react-redux

通过Redux文档来了解react-redux,在一段时间的实践后准备翻一翻源代码,顺便做些相关的总结。我看的代码的npm版本为v4.0.0,也就是说使用的React版本是0.14.x。 react-redux提供两个关键模块...

前端攻城老湿
22分钟前
0
0
1、Mybatis连接池Context.xml配置

注意: (1)mybatis 3.2 之前 通过 set get 方法 获取相关属性。之后通过属性姓名获取相关关联。 (2)mybatis 映射 优先为 sql 语句中的别名与实体类的属性进行映射。 (3)jndi Java用于调...

KingFightingAn
38分钟前
0
0
Android 界面漩涡扭曲动效实现

背景:之前偶然看到优酷有类似的页面切换动画效果。于是自己也打算来实现下这样的效果。 动效说明:点击界面中的任意位置,界面以点击位置作为中心点,开始以漩涡状态,扭曲,收缩。直到消失...

Carlyle_Lee
48分钟前
2
0
聊聊我怎么系统学习Linux技能并快速提高的

聊聊我怎么系统学习Linux技能并快速提高的 随着电子信息科技时代的发展,学会使用计算机在我们的生活中成为了必不可少的一项技能。而作为计算机中的三大操作系统之一的Linux更是饱受计算机爱...

linuxCool
今天
4
0
Android/Java 获取一个byte[]的真实编码,用于解决乱码问题

来源地址:https://blog.csdn.net/qq_31384551/article/details/81627840 一个byte数组,byte[] buf,是由一个字符串转换来的,如何判断字符串使用的是什么编码? Mozilla的一个组件提供了相应...

她叫我小渝
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部