java框架之Hibernate(3)-一對多和多對多關係操做

一對多

例:一個班級能夠有多個學生,而一個學生只能屬於一個班級。java

模型

package com.zze.bean;

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

public class Class {
    private Integer id;
    private String name;

    private Set<Student> students = new HashSet<>();

    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<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}
班級:com.zze.bean.Class
package com.zze.bean;

import java.util.Date;

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Date birthday;
    private String address;

    private Class clazz;

    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 Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }
}
學生:com.zze.bean.Student

配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.bean.Class" table="class">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" length="32"/>
        <!--
        set :
            name : ‘多’的一方在當前類中的屬性名
        -->
        <set name="students">
            <!--
            key :
                column : 外鍵表中的關聯當前類對應表的外鍵名稱
            -->
            <key column="cid"/>
            <!--
            one-to-many : 標識一對多關係
                class : ‘多’的一方全限定類名
            -->
            <one-to-many class="com.zze.bean.Student"/>
        </set>
    </class>
</hibernate-mapping>
com/zze/bean/Class.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.bean.Student" table="student">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" length="32"/>
        <property name="age"/>
        <property name="birthday"/>
        <property name="address"/>
        <!--
        many-to-one : 標識多對一關係
            name : ‘一’的一方在當前類中屬性名
            column : 外鍵名稱
            class : ‘一’的一方的全限定類名
        -->
        <many-to-one name="clazz" column="cid" class="com.zze.bean.Class"/>
    </class>
</hibernate-mapping>
com/zze/bean/Student.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://192.168.208.153:3306/test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.hbm2ddl.auto">create</property>
        <mapping resource="com/zze/bean/Class.hbm.xml"></mapping>
        <mapping resource="com/zze/bean/Student.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>
hibernate.cfg.xml

普通操做

@Test
public void test1() {
    Session session = HibernateUtil.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    // 建立一個班級
    Class clazz = new Class();
    clazz.setName("1班");
    // 建立兩個學生
    Student student1 = new Student();
    student1.setName("張三");
    Student student2 = new Student();
    student2.setName("李四");

    // 讓班級關聯學生
    clazz.getStudents().add(student1);
    clazz.getStudents().add(student2);

    // 讓學生關聯班級
    student1.setClazz(clazz);
    student2.setClazz(clazz);
    // 保存班級
    session.save(clazz);

    // 保存學生
    session.save(student1);
    session.save(student2);
    transaction.commit();
}

例 1:兩方關聯,保存兩方 - 新建一個班級,新建兩個學生,班級主動關聯學生,學生也主動關聯班級,保存班級,再保存學生,成功
@Test
public void test2() {
    Session session = HibernateUtil.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    // 建立一個班級
    Class clazz = new Class();
    clazz.setName("1班");
    // 建立兩個學生
    Student student1 = new Student();
    student1.setName("張三");
    Student student2 = new Student();
    student2.setName("李四");

    // 讓班級關聯學生
    clazz.getStudents().add(student1);
    clazz.getStudents().add(student2);

    // 讓學生關聯班級
    student1.setClazz(clazz);
    student2.setClazz(clazz);
    // 保存班級
    session.save(clazz);
    transaction.commit();

    /*
     拋異常:org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: com.zze.bean.Student
     緣由是:保存班級時,班級關聯的學生爲瞬時態對象,不能與瞬時態對象創建關係。
     */
}
例 2:兩方關聯,保存一方 - 新建一個班級,新建兩個學生,班級主動關聯學生,學生也主動關聯班級,只保存班級,異常,需使用下面的級聯保存。

級聯操做

級聯:

級聯指的是:操做一個對象的時候,是否會同時操做其關聯的對象。mysql

級聯的方向性:

操做一的一方的時候,是否會同時操做到多的一方。sql

操做多的一方的時候,是否會同時操做到一的一方。數據庫

  • 級聯保存或更新

    保存‘一’級聯保存‘多’:session

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="com.zze.bean.Class" table="class">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name" length="32"/>
            <set name="students" cascade="save-update">
                <key column="cid"/>
                <one-to-many class="com.zze.bean.Student"/>
            </set>
        </class>
    </hibernate-mapping>
    com/zze/bean/Class.hbm.xml:修改‘一’(班級)的映射文件,在 set 標籤中添加屬性 cascade="save-update"
    @Test
    public void test3() {
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        // 建立一個班級
        Class clazz = new Class();
        clazz.setName("1班");
        // 建立兩個學生
        Student student1 = new Student();
        student1.setName("張三");
        Student student2 = new Student();
        student2.setName("李四");
    
        // 讓班級關聯學生
        clazz.getStudents().add(student1);
        clazz.getStudents().add(student2);
        // 保存班級級聯保存學生
        session.save(clazz);
        transaction.commit();
    }
    例 3:‘一’方關聯,保存‘一’方 - 新建一個班級,新建兩個學生,班級主動關聯學生,只保存班級,級聯保存了學生,成功

    保存‘多’級聯保存‘一’:app

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="com.zze.bean.Student" table="student">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name" length="32"/>
            <property name="age"/>
            <property name="birthday"/>
            <property name="address"/>
            <many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update"/>
        </class>
    </hibernate-mapping>
    com/zze/bean/Student.hbm.xml:修改‘多’(學生)的映射文件,在 many-to-one 標籤中添加屬性 cascade="save-update"
    @Test
    public void test4(){
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        // 建立一個班級
        Class clazz = new Class();
        clazz.setName("1班");
        // 建立兩個學生
        Student student1 = new Student();
        student1.setName("張三");
        Student student2 = new Student();
        student2.setName("李四");
    
        // 讓學生關聯班級
        student1.setClazz(clazz);
        student2.setClazz(clazz);
        // 保存學生級聯保存班級
        session.save(student1);
        session.save(student2);
        transaction.commit();
    }

     

    例 4:‘多’方關聯,保存‘多’方 - 新建一個班級,新建兩個學生,學生主動關聯班級,只保存學生,級聯保存了班級,成功
  • 級聯刪除

    假如表中已有以下數據:ide

    刪除‘一’級聯刪除‘多’:this

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="com.zze.bean.Class" table="class">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name" length="32"/>
            <set name="students" cascade="save-update,delete">
                <key column="cid"/>
                <one-to-many class="com.zze.bean.Student" />
            </set>
        </class>
    </hibernate-mapping>
    com/zze/bean/Class.hbm.xml:修改‘一’(班級)的映射文件,在 set 標籤中添加屬性 cascade="delete"
    @Test
    public void test5() {
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Class clazz = session.get(Class.class, 1);
        session.delete(clazz);
        transaction.commit();
    }

    例 5:刪除班級,級聯刪除該班級下全部學生。

    刪除‘多’級聯刪除‘一’:url

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="com.zze.bean.Student" table="student">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name" length="32"/>
            <property name="age"/>
            <property name="birthday"/>
            <property name="address"/>
            <many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update,delete"/>
        </class>
    </hibernate-mapping>
    com/zze/bean/Student.hbm.xml:修改‘多’(學生)的映射文件,在 many-to-one 標籤中添加屬性 cascade="delete"
    @Test
    public void test6() {
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Student student = session.get(Student.class, 1);
        session.delete(student);
        transaction.commit();
        // 級聯刪除‘一’的一方,將其它關聯‘一’的一方的數據的外鍵設爲 null。
        // 若是‘一’的一方也設置了級聯刪除,那麼全部關聯‘一’的一方的數據都會被刪除。
    }

    例 6:刪除學生,級聯刪除該學生所屬班級。

放棄維護外鍵關係

假入表中已有以下數據:spa

先要把張三從 1 班轉到 2 班:

@Test
public void test7(){
    Session session = HibernateUtil.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Student student = session.get(Student.class, 1); // 獲取張三
    Class clazz = session.get(Class.class, 1); // 獲取 2 班
    clazz.getStudents().add(student);
    student.setClazz(clazz);
    transaction.commit();
    /*
    此時會執行一下兩條 SQL:
    Hibernate:
        update
            student
        set
            name=?,
            age=?,
            birthday=?,
            address=?,
            cid=?
        where
            id=?
    Hibernate:
        update
            student
        set
            cid=?
        where
            id=?
     */
}
例 7:

執行兩條 SQL 的緣由是:在上述代碼中獲取了兩個持久態對象,而且在事務提交時兩個持久態對象的屬性都發生了變化,因此 Hibernate 發出了兩條 SQL。

但顯然這個操做其實一條 SQL 就能搞定的,這個時候就須要控制一方不維護外鍵關係了。

‘一’的一方放棄維護外鍵關係:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.bean.Class" table="class">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" length="32"/>
        <set name="students" cascade="save-update" inverse="true">
            <key column="cid"/>
            <one-to-many class="com.zze.bean.Student" />
        </set>
    </class>
</hibernate-mapping>
com/zze/bean/Class.hbm.xml:修改‘一’(班級)映射文件,在 set 標籤中添加屬性 inverse="true"

依舊是執行上述「例 7」代碼,會發現只會由‘多’(學生)的一方發出一條 update 語句。

在 Hibernate 中,‘多’的一方不能夠放棄維護外鍵關係。

爲何‘多’的一方不能放棄維護外鍵關係?換句話說爲何 Hibernate 要讓多的一方來維護關係?

緣由是當‘一’的一方維護關係時,Hibernate 會額外發出一條 select 語句查出它所關聯的全部的多的一方,顯然不必。而多的一方維護關係就比較簡單了,直接 update 它自己的外鍵便可。

看到過一個有趣應景的說法:十三億人民(‘多’)記住(維護)國家領導人的名字很簡單,但要想國家領導人(‘一’)記住(維護)十三億就不可能了。

理解 inverse 和 cascade:
@Test
public void test8() {
    // com/zze/bean/Class.hbm.xml 的 set 中設置了 cascade="save-update"、inverse="true"
    Session session = HibernateUtil.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Student student = new Student();
    student.setName("王五");
    Class clazz = session.get(Class.class, 2); // 獲取 1 班
    clazz.getStudents().add(student);
    session.save(clazz);
    transaction.commit();

    /*
    上述代碼執行結果會是怎麼樣?
        先明確 cascade 和 inverse 的做用:
            cascade:爲 save-update,即 Class 會級聯保存和更新 Student。
            inverse:爲 true,即 Class 放棄維護外鍵關係。
        首先 session 保存的是 clazz,clazz 是持久態對象。
        在事務提交時 clazz 的外鍵字段 students 發生了變化,添加了 student,
        班級有級聯操做學生的能力,因此「王五」這個 student 會被保存到數據庫。
        而班級放棄了維護外鍵關係,因此「王五」這個 student 添加到數據庫後對應的外鍵字段爲 null。
    結果以下:
        mysql> select * from student;
        +----+--------+------+----------+---------+------+
        | id | name   | age  | birthday | address | cid  |
        +----+--------+------+----------+---------+------+
        |  1 | 張三   | NULL | NULL     | NULL    |    1 |
        |  2 | 王五   | NULL | NULL     | NULL    | NULL |
        +----+--------+------+----------+---------+------+
        2 rows in set (0.00 sec)
     */
}
例 8:

多對多

例:一名學生能夠選多門課程,一門課程也能夠被多名學生選擇:

模型

package com.zze.bean;

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

public class Student {
    private Integer id;
    private String name;
    private Integer age;
    private Date birthday;
    private String address;

    private Class clazz;

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

    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 Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public Date getBirthday() {
        return birthday;
    }

    public void setBirthday(Date birthday) {
        this.birthday = birthday;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public Class getClazz() {
        return clazz;
    }

    public void setClazz(Class clazz) {
        this.clazz = clazz;
    }

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

    public void setCourses(Set<Course> courses) {
        this.courses = courses;
    }
}
學生:com.zze.bean.Student
package com.zze.bean;

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

public class Course {
    private Integer id;
    private String name;

    private Set<Student> students = new HashSet<>();

    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<Student> getStudents() {
        return students;
    }

    public void setStudents(Set<Student> students) {
        this.students = students;
    }
}
課程:com.zze.bean.Course

配置文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.bean.Student" table="student">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" length="32"/>
        <property name="age"/>
        <property name="birthday"/>
        <property name="address"/>
        <many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update,delete"/>

        <set name="courses" table="student_course">
            <!--
            key :
                column : 當前對象類對應中間表的外鍵名稱
            -->
            <key column="studentId"/>
            <!--
            many-to-many : 標識多對多關係
                class : 對方類全路徑
                column : 對方對應中間表的外鍵名稱
            -->
            <many-to-many class="com.zze.bean.Course" column="courseId"/>
        </set>
    </class>
</hibernate-mapping>
com/zze/bean/Student.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.bean.Course" table="course">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" length="32"/>
        <set name="students" table="student_course">
            <!--
            key :
                column : 當前對象類對應中間表的外鍵名稱
            -->
            <key column="courseId"/>
            <!--
            many-to-many : 標識多對多關係
                class : 對方類全路徑
                column : 對方對應中間表的外鍵名稱
            -->
            <many-to-many class="com.zze.bean.Student" column="studentId"/>
        </set>
    </class>
</hibernate-mapping>
com/zze/bean/Course.hbm.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://192.168.208.153:3306/test</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">root</property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="hibernate.show_sql">true</property>
        <property name="hibernate.format_sql">true</property>
        <property name="current_session_context_class">thread</property>
        <property name="hibernate.hbm2ddl.auto">create</property>
        <mapping resource="com/zze/bean/Class.hbm.xml"></mapping>
        <mapping resource="com/zze/bean/Student.hbm.xml"></mapping>
        <mapping resource="com/zze/bean/Course.hbm.xml"></mapping>
    </session-factory>
</hibernate-configuration>
hibernate.cfg.xml

普通操做

@Test
public void test9() {
    Session session = HibernateUtil.getCurrentSession();
    Transaction transaction = session.beginTransaction();
    Student student = new Student();
    student.setName("張三");
    Course course = new Course();
    course.setName("數學");
    student.getCourses().add(course);
    course.getStudents().add(student);
    session.save(student);
    session.save(course);
    transaction.commit();
    /*
     拋異常:org.hibernate.exception.ConstraintViolationException: could not execute statement
     緣由:由於多對多關係的維護是依賴第三張中間表,而中間表的字段是兩個分別關聯多對多這兩張表的主鍵的外鍵,
     且這兩個外鍵在中間表中組成了聯合主鍵,而上述代碼實際上進行了兩次 insert 操做,這兩次操做的內容違
     反了聯合主鍵約束,因此會拋出異常。
     */
}
例 9:兩方關聯,保存兩方 - 新建一個學生,新建一個課程,讓學生主動關聯課程,也讓課程主動關聯學生,保存學生與課程,異常

分析緣由後,能夠得出結論,在多對多中兩方關聯時,必須有一方得放棄維護外鍵關係(通常是被動方放棄,即 Course 放棄),下面配置二選一:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.bean.Student" table="student">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" length="32"/>
        <property name="age"/>
        <property name="birthday"/>
        <property name="address"/>
        <many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update,delete"/>

        <set name="courses" table="student_course" inverse="true">
            <!--
            key :
                column : 當前對象類對應中間表的外鍵名稱
            -->
            <key column="studentId"/>
            <!--
            many-to-many : 標識多對多關係
                class : 對方類全路徑
                column : 對方對應中間表的外鍵名稱
            -->
            <many-to-many class="com.zze.bean.Course" column="courseId"/>
        </set>
    </class>
</hibernate-mapping>
com/zze/bean/Student.hbm.xml:修改 set 標籤,添加屬性 inverse="true"
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="com.zze.bean.Course" table="course">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name" length="32"/>
        <set name="students" table="student_course" inverse="true">
            <!--
            key :
                column : 當前對象類對應中間表的外鍵名稱
            -->
            <key column="courseId"/>
            <!--
            many-to-many : 標識多對多關係
                class : 對方類全路徑
                column : 對方對應中間表的外鍵名稱
            -->
            <many-to-many class="com.zze.bean.Student" column="studentId"/>
        </set>
    </class>
</hibernate-mapping>
com/zze/bean/Course.hbm.xml:修改 set 標籤,添加屬性 inverse="true"

修改配置後,再次執行 「例 9」 中代碼,成功。

級聯操做

  • 級聯保存或更新

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="com.zze.bean.Student" table="student">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name" length="32"/>
            <property name="age"/>
            <property name="birthday"/>
            <property name="address"/>
            <many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update,delete"/>
    
            <set name="courses" table="student_course" cascade="save-update">
                <!--
                key :
                    column : 當前對象類對應中間表的外鍵名稱
                -->
                <key column="studentId"/>
                <!--
                many-to-many : 標識多對多關係
                    class : 對方類全路徑
                    column : 對方對應中間表的外鍵名稱
                -->
                <many-to-many class="com.zze.bean.Course" column="courseId"/>
            </set>
        </class>
    </hibernate-mapping>
    com/zze/bean/Student.hbm.xml:修改 set 標籤,添加屬性 cascade="save-update"
    @Test
    public void test10() {
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Student student = new Student();
        student.setName("張三");
        Course course = new Course();
        course.setName("數學");
        student.getCourses().add(course);
        session.save(student);
        transaction.commit();
    }
    例 10:一方關聯,保存一方 - 新建一個學生,新建一個課程,讓學生主動關聯課程,保存學生,級聯保存了課程,成功
  • 級聯刪除

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE hibernate-mapping PUBLIC
            "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
            "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
    
    <hibernate-mapping>
        <class name="com.zze.bean.Student" table="student">
            <id name="id">
                <generator class="native"/>
            </id>
            <property name="name" length="32"/>
            <property name="age"/>
            <property name="birthday"/>
            <property name="address"/>
            <many-to-one name="clazz" column="cid" class="com.zze.bean.Class" cascade="save-update,delete"/>
    
            <set name="courses" table="student_course" cascade="save-update,delete">
                <!--
                key :
                    column : 當前對象類對應中間表的外鍵名稱
                -->
                <key column="studentId"/>
                <!--
                many-to-many : 標識多對多關係
                    class : 對方類全路徑
                    column : 對方對應中間表的外鍵名稱
                -->
                <many-to-many class="com.zze.bean.Course" column="courseId"/>
            </set>
        </class>
    </hibernate-mapping>
    com/zze/bean/Student.hbm.xml:修改 set 標籤,添加屬性 cascade="delete"
    @Test
    public void test11() {
        Session session = HibernateUtil.getCurrentSession();
        Transaction transaction = session.beginTransaction();
        Student student = session.get(Student.class, 1);
        session.delete(student);
        transaction.commit();
    }
    例 11:刪除學生,級聯刪除該學生所選的課程
相關文章
相關標籤/搜索