天天看點

【Hibernate系列】(六):關聯映射之一對多前言一對多一對多和多對一結合總結

前言

  在閱讀本篇部落格之前,請先對多對一關聯映射有所了解,可參考【Hibernate系列】(五):關聯映射之多對一 。在上篇部落格中,我們已經強調過,多對一和一對多的關聯映射原理都是在多的一端加入外鍵。它們在對象模型中的差別就是從誰能看到誰的問題。如:在上篇文章的例子中,通過user可以加載出group來,但是不能通過group來加載user。這篇文章,我們着重強調單純一對多關系的配置,以及一對多和多對一同時存在時的配置。

一對多

關系模型和映射原理

這裡隻是友善大家和後面的代碼對應。模型和原理同多對一。

   

【Hibernate系列】(六):關聯映射之一對多前言一對多一對多和多對一結合總結

  

【Hibernate系列】(六):關聯映射之一對多前言一對多一對多和多對一結合總結

配置

★Classes.java
package com.bjpowernode.hibernate;

import java.util.Set;

public class Classes {

    private int id;

    private String name;
    //關聯對象集合,沒有使用泛型
    private Set students;

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

    public void setStudents(Set students) {
        this.students = students;
    }

}
           
★Classes.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>
    <class name="com.bjpowernode.hibernate.Classes" table="t_classes">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <set name="students">
            <!--指定外鍵字段名稱-->         
            <key column="classesid"/>
            <!--通過class屬性指定關聯集合中存儲的實體類型-->
            <one-to-many class="com.bjpowernode.hibernate.Student"/>
        </set>
    </class>
</hibernate-mapping>
           
Students.java和Student.hbm.xml中未進行任何配置,這裡省略它們的代碼。

對象的存儲和加載

  因為隻在一端進行了配置,是以我們可以猜到能夠通過Classes加載Student,反之則不行。而且這個關聯關系也是由Classes來維護的,是以存儲的時候,應該先存儲Student,再存儲Classes。即:關系由誰維護誰就後存儲,另外的對象先存儲。
public void testSave2() {
        Session session = null;
        try {
            session = HibernateUtils.getSession();
            session.beginTransaction();
            Student student1 = new Student();
            student1.setName("張三");
            session.save(student1);

            Student student2 = new Student();
            student2.setName("李四");
            session.save(student2);

            Classes classes = new Classes();
            classes.setName("動力節點");

            Set students = new HashSet();
            students.add(student1);
            students.add(student2);
            classes.setStudents(students);

            //可以成功儲存資料
            //但是會發出多餘的update語句來維持關系
            session.save(classes);
            session.getTransaction().commit();
        }catch(Exception e) {
            e.printStackTrace();
            session.getTransaction().rollback();
        }finally {
            HibernateUtils.closeSession(session);
        }
    }
           

因為關系由class維護,是以先存儲student,但是存儲student的時候,還不知道classesid是什麼,是以代碼運作時會列印出以下結果:在save的時候插入資料,在commit的時候更新(外鍵)。

Hibernate: insert into t_student (name) values (?)

Hibernate: insert into t_student (name) values (?)

Hibernate: insert into t_classes (name) values (?)

Hibernate: update t_student set classesid=? where id=?

Hibernate: update t_student set classesid=? where id=?

發的語句越多說明和資料庫互動越多,影響性能。

加載此處省略,可以通過classes加載student。

一對多和多對一結合

單純的多對一,我們可以通過“多”加載“一”,不能通過“一”加載“多”。

單純的一對多,我們可以通過“一”加載“多”,不能通過“多”加載“一”,同時還存在影響性能的弊端。

是以,我們可能會單獨使用多對一,但是很少會單獨的使用一對多。

那麼,如何能滿足我們的需求,又能避免以上缺點呢?

配置

我們采取的方式一對多和多對一兩個關系都配置上,隻是關系由多的一方維護,也就是最關鍵的地方即在一的一端将inverse屬性設定為true。

一的一端隻修改了配置檔案。

<hibernate-mapping>
    <class name="com.bjpowernode.hibernate.Classes" table="t_classes">
        <id name="id">
            <generator class="native"/>
        </id>
        <property name="name"/>
        <!--inverse設定為true,關系由對端維護-->
        <set name="students" inverse="true">            
            <key column="classesid"/>
            <one-to-many class="com.bjpowernode.hibernate.Student"/>
        </set>
    </class>
</hibernate-mapping>
           

多的一端的配置參考上一篇文章即可,這裡省略.

存儲就可以按多對一的時候的存儲步驟進行存儲了。此時兩個對象也可以互相加載了。具體代碼參考上一篇部落格。

總結

  通過多對一和一對多關聯關系的學習,我們可以歸納出,配置

<many-to-one>

<one-to-many>

标簽決定的是能否加載關聯對象;但是關系由誰維護,決定如何存儲對象。

繼續閱讀