zoukankan      html  css  js  c++  java
  • (转)Hibernate框架基础——cascade属性

    http://blog.csdn.net/yerenyuan_pku/article/details/52760010

    我们以部门和员工的关系为例讲解一对多关联关系映射时,删除部门时,如果部门有关联的员工且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属性毛关系都没有。

  • 相关阅读:
    马哥博客作业第四周
    马哥博客作业第三周
    马哥博客作业第二周
    马哥博客作业第一周
    YUM常用命令
    RPM常用命令
    马哥博客作业第五周
    《现代操作系统》—— 第9章 文件系统(一)
    《现代操作系统》—— 第8章 存储模型(二) 虚拟存储技术
    《现代操作系统》—— 第7章 存储模型(一)
  • 原文地址:https://www.cnblogs.com/telwanggs/p/6963427.html
Copyright © 2011-2022 走看看