今天繼續學習Heribernate,湯老師在Heribernate 原理上做了更深入的講解,講了Session的方法對Heribernate對象實例的三種狀態進行轉換,Heribernate實體間的映射關係,一對一,一對多。並舉例進行講解, 例子敲了一遍,加深理解。
Heribernate對象實例的三種狀態之間通過Session的方法,可以進行轉換。
Session的方法:save(persist), delete, get, load.
update:update是把一個已經更改過的遊離狀態的對象變成持久狀態。
saveOrUpdate(merge):什麼下情況添加什麼情況下更新,這要根據unsaved-value屬性的設置,該屬性爲TRUE時,則添加,該屬性爲false時,這爲更新;
使用save和saveOrUpdate方法時,如果被操作對象與另一個跟本session 關聯的對象擁有相同的持久化標識(identifier),就會拋出一個異常:org.hibernate.NonUniqueObjectException。
通常下面的場景會使用update()或saveOrUpdate():程序在第一個 session 中加載對象,接着把session關閉,該對象被傳遞到表現層,對 象發生了一些改動,該對象被返回到業務邏輯層最終到持久層,程序創建第二session調用第二個session的update()方法持久這些改動。 contains:Session是否包含某個對象(也是判斷是否是持久狀態);
clear:清空一級緩存;
flush:強制刷出(更新到數據庫);
load與get的區別主要在於返回結果的不同:
get方法:如果找不到符合條件的紀錄,返回null。
load方法:返回的是一個代理對象。在第一次訪問這些懶加載對象(代理對象)的屬性(getId方法除外)時,hibernate 會初始化這些代理。這 時如果數據庫中沒有與之對應的記錄,就會拋出如下的異常: org.hibernate.ObjectNotFoundException: No row with the given
identifier exists: ...。
如果Heribernate實體是final的,則load被調用時會馬上發出一條select語句(即不能使用懶加載功能),所以推薦Heribernate實體類不是final的。
關聯映射:
一對多與多對一映射:有兩個類User與Group;Group類有屬性: id:int, name:string;
1,單向多對一:
在User中增加屬性group,並在User.hbm.xml中增加:
<many-to-one name="group" column="groupId" (not-null="true")></many-to-one>
使用代碼:
session.save(group);
user.setGroup(group);
session.save(user);
2,雙向關聯,一對多、多對一:
在上一步的基礎上:在Group中增加屬性users:Set<User>;在
Group.hbm.xml中增加:
<set name="users">
<key column="groupId"></key>
<one-to-many class="User"/>
</set>
<one-to-many>不需要定義任何字段,也不需要指定表名。
<key>元素在父映射元素定義了對新表的連接,並且在被連接表中定義了一個外鍵引用原表的主鍵的情況下經常使用。其中column指的是外鍵字段的名稱。 使用代碼:1,第一步中的代碼。或
2:session.save(user);
group.getUsers().add(user);
session.save(group);
// 這樣要求groupId列允許空值.
在Set中不能添加重複的元素,是否重複是由hashCode和equals方法決定的。所以
要重寫hashCode與equals方法:
hashCode:IF id==null THEN return super.hashCode。
基於外鍵的單向一對一。和單向多對一關聯幾乎一樣,唯一的不同就是單向 一對一關聯中的外鍵字段具有唯一性約束。在IdCard.hbm.xml中增加:<many-to-one name="userxx" unique="true" />(外鍵在哪張表中, many-to-one元素就在那個表相應實體的映射文件中)。
使用代碼:
idCard.setUser(user);
session.save(user);
session.save(idCard);