zoukankan      html  css  js  c++  java
  • 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();  
    }  
  • 相关阅读:
    fullCalendar改造计划之带农历节气节假日的万年历(转)
    Linked List Cycle
    Remove Nth Node From End of List
    Binary Tree Inorder Traversal
    Unique Binary Search Trees
    Binary Tree Level Order Traversal
    Binary Tree Level Order Traversal II
    Plus One
    Remove Duplicates from Sorted List
    Merge Two Sorted Lists
  • 原文地址:https://www.cnblogs.com/luckygxf/p/4548481.html
Copyright © 2011-2022 走看看