Hibernate的一对多自关联中的级联删除问题

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Hibernate的一对多自关联中的级联删除问题相关的知识,希望对你有一定的参考价值。

我正在开发一个论坛,论坛的父版块和子版块之间是一对多自关联关系,删除一个父版块对象必须级联删除与之关联的子版块对象。我在Hibernate的映射文件中是这样配置的,应该没错:
<set name="childBoards" cascade="all" outer-join="true">
<key column="PARENTID"/>
<one-to-many class="Board"/>
</set>
<many-to-one class="Board" cascade="none" column="PARENTID" name="parent" not-null="false" outer-join="true"/>
但是就是无法实现一对多级联删除,删除父版块记录之后,子版块记录依然还在,没被删除,这是怎么回事啊?
我已经设置了default-lazy="false"属性了,还是没用。

参考技术A 1)一对多采取了延迟加载策略:lazy="true"默认
2)将多传播持久性(级联)设置为最全面的全部级联(包括孤儿模式):cascade="all-delete-orphan"
3)将维护关系的控制权交给多端:inverse="true"
参考技术B 刚看错了 - -!

SSH三大框架Hibernate基础第九篇:cascade关联关系的级联操作

这里要说的是Hibernate的关联关系的级联操作,使用cascade属性控制。


依旧用部门和员工举例。多个员工相应一个部门(多对一关联关系)

员工类:Employee.java

package cn.itcast.hibernate.domain;

public class Employee {  
    private int id;  
    private String name;  
    private Department depart;  
      
    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 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="cn.itcast.hibernate.domain"> <class name="Employee" table="tb_Employee"> <id name="id"> <generator class="native"/> </id> <property name="name" /> <many-to-one name="depart" column="depart_id" /> </class> </hibernate-mapping>

部门类:Department.java

package cn.itcast.hibernate.domain;

import java.util.Set;

public class Department {  
    private int id;  
    private String name;  
    private Set<Employee> emps;
    
    public Set<Employee> getEmps() {
		return emps;
	}
	public void setEmps(Set<Employee> emps) {
		this.emps = 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;  
    }  
}  
部门映射文件:Department.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="cn.itcast.hibernate.domain">  
  
    <class name="Department" table="tb_Department">  
        <id name="id">  
            <generator class="native"/>   
        </id>  
        <property name="name" />  
        
        <set name="emps" cascade="save-update">
        	<key column="depart_id" />
        	<one-to-many class="Employee" />
        </set>
    </class>  
      
</hibernate-mapping>  
能够看到,在上边的set标签中。我们定义了cascade="save-update"属性,当session通过save(),update(),saveOrUpdate()方法来保存或更新对象时,级联保存全部关联的新建的暂时对象。而且级联更新全部关联的游离对象

我们来写一个測试类:Many2One.java

package cn.itcast.hibernate;

import java.util.HashSet;
import java.util.Set;

import org.hibernate.Hibernate;
import org.hibernate.Session;
import org.hibernate.Transaction;

import cn.itcast.hibernate.domain.Department;
import cn.itcast.hibernate.domain.Employee;

public class Many2One {  
    public static void main(String[] arg){  
        Department depart = add();  
  
        delete(1);
    }  
      
    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 name");  
            
            
            Employee emp2 = new Employee();  
            emp2.setDepart(depart); //建立两个对象的关联关系  
            emp2.setName("emp name");  
            
    
            Set<Employee> emps = new HashSet<Employee>();
            //把两个Employee对象加入到set集合中
            emps.add(emp1);
            emps.add(emp2);
            //为Department对象注入set集合属性
            depart.setEmps(emps);
            
            s = HibernateUtil.getSession();  
            tx = s.beginTransaction();  
           
            //保存Department对象
            s.save(depart); 
            
            tx.commit();  
            return depart;  
        }finally{  
            if(s!=null){  
                s.close();  
            }  
        }  
    }  
      
    static Department delete(int departId){  
        Session s = null;  
        Transaction tx = null;  
        try{  
            s = HibernateUtil.getSession();  
            tx = s.beginTransaction();  
            Department depart = (Department)s.get(Department.class, departId); //依据ID查询  
            s.delete(depart);
            
            tx.commit();  
            return depart;  
        }finally{  
            if(s!=null){  
                s.close();  
            }  
        }  
    }  
}  
能够看到我们定义了两个方法:add()和delete()

add():在这种方法中。我们在保存的时候只保存了Department对象。可是依据cascade="save-update"属性。两个Employee对象也会保存在数据库中

delete():在这种方法中,我们想通过直接删除Department对象使得数据库中与Department表关联的Employee表中的数据删除。可是。我们配置的cascade是要求在保存或者更新的时候发生级联关系,所以假设我们运行delete()方法后,仅仅会在Department表的数据被删除。Employee表的数据的外键会变成null。可是数据不会被删除


下边我们来看下cascade的取值:

Cascade属性的取值有:

1、none:忽略其它关联的对象。默认值。



2、save-update:当session通过save(),update(),saveOrUpdate()方法来保存或更新对象时,级联保存全部关联的新建的暂时对象。而且级联更新全部关联的游离对象。



3、persist:当session通过persist()方法来保存当前对象时。会级联保存全部关联的新建的暂时对象。

4、merge:通过Session的merge()方法来保存当前对象时。会级联融合全部关联的游离对象。

5、delete:通过delete()删除当前对象时,会级联删除全部关联的对象。

6、lock:通过lock()把当前游离对象增加session缓存时。会把全部的游离对象也增加Session缓存中。



7、replicate:通过replicate()复制当前对象时,会级联复制全部关联的对象。

8、evict:通过evict()清除session缓存中对象时,会级联清除全部关联的对象。



9、refresh:通过refresh()刷新当前对象时,会级联刷新全部关联的对象。

(刷新是指同步更新session缓存中数据)

10、all:save-update(),persist(),merge(),delete(),lock(),replicate(),evict()及refresh()的行为。

11、delete-orphan,删除全部和当前对象时。解除关联行为的对象。



12、all-delete-orphan; 通过delete()删除当前对象时,会级联删除全部关联的对象。







































以上是关于Hibernate的一对多自关联中的级联删除问题的主要内容,如果未能解决你的问题,请参考以下文章

JPA Hibernate - 数据库和注释中的级联删除

mybatis 级联

关联映射级联操作关系维护 ---- Hibernate之一对多|多对一关系

hibernate一对多单向关联时更新问题

hibernate多对多双向关系映射的级联配置

Hibernate 一对多关系级联删除