? ? 在上一篇博客《[一口一口吃掉Hibernate(四)——多對一單向關聯映射](http://blog.csdn.net/xiaoxian8023/article/details/11827551)》中,介紹了多對一的關聯映射,今天就反過來說一下一對多的單向關聯映射。
? ??可能有人會對這2篇博客的題目有點混淆不清,跟日常說的關系有點不同。我們日常說的比如父子關系,夫妻關系都是說的雙向關系,而現在討論的則是單向關系,所以也就有了多對一和一對多的說法。
? ? 二者的關系其實很簡單,只是角度不同而已。比如說學生和班級的關系。如果從學生角度來看,是多對一的關系。而從班級角度來看,則是一對多的關系。說法很簡單,但是在對象和關系的建立卻是不一樣的。
? ? 先看一下一對多的類圖(貌似好多人的聚合關系都畫錯了):

? ?Hibernate對于一對多的關系的處理,是通過操作Class端,間接操作或者自動操作Student端。比如添加,我直接添加Class端的數據,多個Student就會被添加自動添加進去。也可以通過這個Class獲取到所有對應的學生信息。跟著我來配置一下吧:
? ? 首先定義實體類【Class】【Student】
~~~
package com.bjpowernode.hibernate;
import java.util.Set;
/**
* 班級類
* @author Longxuan
*
*/
public class Class {
private int id;
private String name;
private Set<Student> students;
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = 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;
}
}
package com.bjpowernode.hibernate;
/**
* 學生類
* @author Longxuan
*
*/
public class Student {
private int id;
private String name;
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;
}
}
~~~
? ??hibernate.cfg.xml配置文件和hibernate.properties配置文件跟上篇博文中的一致,只是數據庫名不同而已。自行修改或者不修改都可。
? ? Hibernate提供了one-to-many來簡化一對多的映射關系。不用我們自己再去實現,只需要在映射文件中進行配置即可:
~~~
<?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 package="com.bjpowernode.hibernate">
<class name="Student" table="t_student">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
</class>
<class name="Class" table="t_class">
<id name="id">
<generator class="native"/>
</id>
<property name="name"/>
<!-- 設置Set,用于關聯多個學生 -->
<set name="students">
<!-- 在t_student表中創建外鍵classid,與本表的id對應 -->
<key column="classid"></key>
<one-to-many class="Student"></one-to-many>
</set>
</class>
</hibernate-mapping>
~~~
? ? 配置了one-to-many會自動在t_student表中創建外鍵classid,與t_class的id映射。

? ? 測試類【One2ManyTest】:
~~~
package com.bjpowernode.hibernate;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import junit.framework.TestCase;
import org.hibernate.Session;
import org.hibernate.Transaction;
public class One2ManyTest extends TestCase {
public void testSave2() {
Session session = null;
try {
session = HibernateUtils.getSession();
session.beginTransaction();
Student student1 = new Student();
student1.setName("張三");
//必須先將student1轉化為Persistent狀態,否則會拋TransientObjectException
session.save(student1);
Student student2 = new Student();
student2.setName("李四");
//必須先將student1轉化為Persistent狀態,否則會拋TransientObjectException
session.save(student2);
Class classes = new Class();
classes.setName("提高班");
Set<Student> students = new HashSet<Student> ();
students.add(student1);
students.add(student2);
classes.setStudents(students);
//可以成功保存數據。
//先添加數據,將關系字段設置為null,再用update語句來更新關系字段
//但是會發出多余的update語句來維持關系。
session.save(classes);
session.getTransaction().commit();
}catch(Exception e) {
e.printStackTrace();
session.getTransaction().rollback();
}finally {
HibernateUtils.closeSession(session);
}
}
~~~
? ? 結果圖:

? ? 執行測試前:
,執行測試后:
? ? 雖然最后的結果跟多對一一樣,但是根據sql語句,就可以看出,一對多是先添加student,classid為null,等添加了class以后,再執行update語句,把classid更新上去。這樣同時可能會暴露一個問題:如果student的classid設置了not-null="true",則會拋PropertyValueException異常。所以不太推薦使用一對多。
? ? 通過上面的例子,我們可以看出,其實一對多關聯映射和多對一關聯映射映射原理是一致的,都是在多的一端加入一個外鍵,指向一的一端。
? ? 它們的區別在于維護的關系不同:
- 多對一維護的關系是:多指向一的關系,有了此關系,在加載多的時候可以**先**將一加載上來
- 一對多維護的關系是:一指向多的關系,有了此關系,在加載一的時候可以**先**將多加載上來
? ? 在一的一端維護關系存在缺陷:
- 因為多的一端Student不知道Class的存在(也就是Student沒有維護與Class的關系)所以在保存Student的時候關系字段classid是為null的,如果將該關系字段設置為非空,則將無法保存數據
- 另外因為Student不維護關系,而Class維護關系,Class就會發出多余的update語句,保證Class和Student有關系,這樣加載Class的時候才可以把該Class對應的學生加載上來
- 前言
- Struts 簡單小結
- 深入淺出了解Struts的處理流程(有圖有真相)
- struts標簽+jstl標簽之國際化實例
- 一口一口吃掉Hibernate(二)——別被世俗蒙蔽了雙眼:Hibernate中Session之get和load方法的真正區別
- 一口一口吃掉Hibernate(一)——使用SchemaExport生成數據表
- 一口一口吃掉Hibernate(三)——Hibernate給表和字段設置前后綴及分隔符
- 一口一口吃掉Hibernate(四)——多對一單向關聯映射
- 一口一口吃掉Hibernate(五)——一對多單向關聯映射
- 一口一口吃掉Hibernate(六)——多對多關聯映射
- 一口一口吃掉Hibernate(七)——繼承映射
- 一口一口吃掉Hibernate(八)——Hibernate中inverse的用法
- 一覽Spring全貌
- 包辦婚姻的Spring IoC
- 3幅圖讓你了解Spring AOP
- Spring Aop實例之xml配置
- Spring Aop實例之AspectJ注解配置