Hibernate多对多删除问题的解决

原出处:http://superleo.iteye.com/blog/154587

Hibernate多对多的例子不少,但仔细一看,大多数都是保存的,删除谈的少,但问题还不少,因此有必须简单测试一下,以下我们来个简单的多对多关系建立
老师Teacher 与 课程Course 是一个多对多的关系,Pojo与XMl配置如下。

Pojo
Java代码  收藏代码
/**
 * Course Entity
 * see table: tbl_course
 */
package com.leo.domain;  

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

/**
 * @author superleo
 *
 */
public class Course {  

    private String id;  

    private String name;  

    private Set<Teacher> teachers = new HashSet<Teacher>();  

    public String getId() {
        return id;
    }  

    public void setId(String id) {
        this.id = id;
    }  

    public String getName() {
        return name;
    }  

    public void setName(String name) {
        this.name = name;
    }  

    public Set<Teacher> getTeachers() {
        return teachers;
    }  

    public void setTeachers(Set<Teacher> teachers) {
        this.teachers = teachers;
    }  

}
Java代码  收藏代码
/**
 * Teacher Entity
 * see table: tbl_teacher
 */
package com.leo.domain;  

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

/**
 * @author superleo
 *
 */
public class Teacher {  

    private String id;  

    private String name;  

    private Set<Course> courses = new HashSet<Course>();  

    public String getId() {
        return id;
    }  

    public void setId(String id) {
        this.id = id;
    }  

    public String getName() {
        return name;
    }  

    public void setName(String name) {
        this.name = name;
    }  

    public Set<Course> getCourses() {
        return courses;
    }  

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }  

}  

配置文件也非常简单:
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.leo.domain.Course" table="tbl_course"
        batch-size="100" dynamic-insert="true" dynamic-update="true">
        <id name="id" column="id">
            <generator class="uuid" />
        </id>
        <property name="name" column="name" type="string" />  

        <set access="property" lazy="true" inverse="false"
            cascade="save-update" name="teachers" batch-size="10" fetch="select"
            table="tbl_teacher_course">
            <key column="fk_course_id" />
            <many-to-many class="com.leo.domain.Teacher"
                column="fk_teacher_id" />
        </set>  

    </class>
</hibernate-mapping>
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.leo.domain.Teacher" table="tbl_teacher"
        batch-size="100" dynamic-insert="true" dynamic-update="true">
        <id name="id" column="id">
            <generator class="uuid" />
        </id>
        <property name="name" column="name" type="string" />  

        <set access="property" lazy="true" inverse="true"
            cascade="save-update" name="courses" batch-size="10" fetch="select"
            table="tbl_teacher_course">
            <key column="fk_teacher_id" />
            <many-to-many class="com.leo.domain.Course"
                column="fk_course_id" />
        </set>  

    </class>
</hibernate-mapping>  

先往数据库里插入一些记录:

Java代码  收藏代码
public void testSave() {
        Session session = HibernateSessionFactory.getSession();
        session.beginTransaction();  

        // create course
        Course c1 = new Course();
        Course c2 = new Course();
        c1.setName("C");
        c2.setName("Java");  

        // create teacher
        Teacher t1 = new Teacher();
        Teacher t2 = new Teacher();
        t1.setName("Leo");
        t2.setName("Rose");  

        // create relationship
        c1.getTeachers().add(t1);
        c1.getTeachers().add(t2);
        t1.getCourses().add(c1);
        t2.getCourses().add(c1);  

        /* 因为主控方级联设置为save-update,如果设置为none,则下面被注释的代码需要开启,否则会报错 */
        //session.save(t1);
        //session.save(t2);
        session.save(c1);  

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

下面是测试的一些结果:
1. 如果cascade不管主控方设置还是被控方设置成 all, delete等与delete级联删除有关即可,两端以及中间表的记录都会被删除,通常这样的需要是很少的,因此,如果你要这样的情况,只要简单设置成all, delete就可以轻松的将关系以及两端的记录删除的干干净净。
2. 只想删除某一端的记录以及中间的表的关联信息。 这种需求通常是很常见的。这个时候cascade的设置是除与delete有关的任何级联约束。以下是删除心得:
如果删除的是主控方,只需要简单的删除这条记录,级联关系以及主控方的记录同时删除,但被控方的记录仍然存在。因此只对主控方的多对多删除是最简单,直接的。代码如下:
Java代码  收藏代码
/**
     * 多对多 主控方删除(可以删除中间表记录)
     */
    public void testDelete() {
        String id = "402881ee175f04be01175f04c05d0001";
        Session session = HibernateSessionFactory.getSession();
        session.beginTransaction();
        Course c1 = (Course) session.get(Course.class, id);
        session.delete(c1);
        session.getTransaction().commit();
        session.close();
    }  

如果你这个时候想直接删除被控方,那么很遗憾的告诉你,你只做到了一半,你只是简单的把被控方的记录删除了,关联关系仍然存在中间表里,系统随时会因为你的关联访问报错,代码如下:
Java代码  收藏代码
/**
 * 多对多 被控方删除(无法删除中间表记录)
 */
public void testDeleteByInverse() {
    String id = "402881ee175a2e7c01175a2e7ead0003";
    Session session = HibernateSessionFactory.getSession();
    session.beginTransaction();
    Teacher t1 = (Teacher) session.get(Teacher.class, id);
    session.delete(t1);
    session.getTransaction().commit();
    session.close();
}  

如果想既想删除被控方,双想删除关联,请看下面代码:
Java代码  收藏代码
/**
 * 多对多 被控方删除(可以删除中间表记录)
 */
public void testDeleteByInverse2() {
    String id = "402881ee175f04be01175f04c06c0002";
    Session session = HibernateSessionFactory.getSession();
    session.beginTransaction();  

    Teacher t1 = (Teacher) session.get(Teacher.class, id);  

    Set<Course> cs = t1.getCourses();
    for (Course c : cs) {
        c.getTeachers().remove(t1);
    }  

    session.delete(t1);
    session.getTransaction().commit();
    session.close();
}  
时间: 2024-10-30 05:10:32

Hibernate多对多删除问题的解决的相关文章

hibernate多对多中间表设计

hibernate多对多中间表,一般都是两个外键,例如 用户表(user),主键:userid. 角色表(role),主键:roleid. 中间表字段为两个外键:userid,roleid作为联合主键. 但是如果想在中间表加一个字段作为单独的主键,即设置一个字段id作为主键.并且数据库采用的是oracle数据库,主键不能自增.那么采用hibernate向中间表插数据的时候,就会出现问题,即主键id字段插入为空,会报错误. 由于oracle不支持自动编号,为解决以上错误,我们还得为oracle数据

Hibernate多对多级联操作

表与表之间关系回顾(重点) 2 多对多 (1)订单和商品关系,一个订单里面有多个商品,一个商品属于多个订单 (2)用户和角色多对多关系 - 用户: 小王.小马.小宋 - 角色:总经理.秘书.司机.保安 ** 比如小王 可以 是总经理,可以是司机 ** 比如小宋 可以是司机,可以是秘书,可以保安 ** 比如小马 可以是 秘书,可以是总经理 -          一个用户里面可以有多个角色,一个角色里面可以有多个用户 (3)多对多建表:创建第三张表维护关系 Hibernate多对多操作 多对多映射配

05.Hibernate多对多关联

前言:本文讲解使用Hibernate映射多对多关联关系,并使用多种方式映射多对多关联. 1.数据库表的多对多关系 本文根据学生信息表(tb_student)和教师信息表(tb_teacher)来说明多对多映射关系,一个学生有多个老师,一个老师也有多个学生,其数据库模型图如下: 根据以上图,对应的建表语句如下: CREATE TABLE tb_student ( id bigint NOT NULL auto_increment COMMENT 'ID', no varchar(10) NOT N

hibernate多对多关系配置--增删改查

hibernate多对多关联配置--并实现增删改查 hibernate就不多介绍了,这里就直接上我项目中使用的例子做说明. 数据模型 这是项目中用户和用户组的数据模型er图草稿,具体的model对象字段就以项目中的为主了. model类以及pojo接口,这里pojo接口用不上,大家测试的时候也可以去掉 package com.supre.model; import java.io.Serializable; import java.util.Set; public class User { pr

无法删除DLL文件解决方法(转)

无法删除DLL文件解决方法(转) 手动解决dll文件无法删除的终极方法 手动解决dll文件无法删除的终极方法 相信大家都遇见过:在删除一些软件的时候弹出某某文件正在运行或磁盘写保护不能删除这样的报错提示吧.而常常删除不掉的都一些后缀为.dll的文件.到底这个dll文件是什么文件,如何才能知道是哪些程序在调用这个dll文件呢? [基础理论]dll文件英文名称为Dynamic Linking Library,以下简称dll,中文名字"动态链接程序库"文件.在Windows中,许多应用程序并

Hibernate 插入,修改,删除,查询语句

/* *具体操作hibernate的类 *增加,删除,修改,按ID查询,模糊查询,查询全部 **/ public class PersonOperate { //在hibernate中所有操作都是由Session完成 public Session session = null; //在构造方法中实例化Session对象 public PersonOperate(){ //找出hibernate的配置 Configuration config = new Configuration().confi

android 下拉刷新上拉加载更多,高仿ios左滑动删除item,解决了众多手势问题

一.前言 老规矩,别的不说,这demo是找了很相关知识集合而成的,可以说对我这种小白来说是绞尽脑汁!程序员讲的是无图无真相!现在大家一睹为快! 二.比较关键的还是scroller这个类的 package com.icq.slideview.view; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.util.TypedValue; i

SSH学习 Hibernate 多对多

Hibernate 多对多关系的处理,是把两个po类(持久化类)分别建表,这两个是要自己写po类和对应的映射文件,两个表的关系另外再建一张表,这个关系表不需要有对应的类,只需在映射文件写必要的标签即可 注明一点:fetch = "join" fetch参数指定了关联对象抓取的方式是select查询还是join查询,select方式时先查询返回要查询的主体对象(列表),再根据关联外键id,每一个对象发一个select查询,获取关联的对象,形成n+1次查询: 而join方式,主体对象和关联

SSH项目web.xml文件的常用配置【struts2的过滤器、spring监听器、解决Hibernate延迟加载问题的过滤器、解决中文乱码的过滤器】

配置web.xml(struts2的过滤器.spring监听器.解决Hibernate延迟加载问题的过滤器.解决中文乱码的过滤器) <!-- 解决中文乱码问题 --> <filter> <filter-name>characterEncodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-c