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