hibernate學習筆記 1

笨笨鼠→_→發表於2012-07-06

1-hb初步

第一個hibernate專案

1、新建java專案

2、建立User Library,加入如下jar
 * HIBERNATE_HOME/hibernate3.jar
 * HIBERNATE_HOME/lib/*.jar
 * MySql jdbc驅動
 
3、建立hibernate配置檔案hibernate.cfg.xml,為了便於除錯最好加入log4j配置檔案

4、定義實體類

5、定義User類的對映檔案User.hbm.xml

6、將User.hbml.xml檔案加入到hibernate.cfg.xml檔案中

7、編寫hbm2ddl工具類,將實體類生成資料庫表

8、開發客戶端
 
為了方便跟蹤sql執行,在hibernate.cfg.xml檔案中加入<property name="hibernate.show_sql">true</property>


2-測試實體物件的生命週期

junit簡介:
 * 編寫測試類xxxTest,需要繼承TestCase
 * 編寫單元測試方法,測試方法必須以test開頭,測試方法不能含有引數和返回值,如:
   public void testHello1() {}
 * 最好單元測試的程式碼單獨建立一個目錄
 
瞭解Hibernate中CRUD操作

瞭解get和load的區別?
 * get不支援lazy,load支援lazy
 * 採用get載入資料,如果沒有匹配的資料,返回null,而load則丟擲異常
 
transient狀態的特徵?
 * 在資料庫中沒有與之匹配的資料
 * 沒有納入session的管理
 
persistent狀態的特徵?
 * persistent狀態的物件在資料庫中有與之匹配的資料
 * 納入了session的管理
 * 在清理快取(髒資料檢查)的時候,會和資料庫同步
 
detached狀態的特徵?
 * 在資料庫中有與之匹配的資料
 * 沒有納入session的管理  


3-hibernate基本對映


實體類---表
實體類中的普通屬性---表欄位

採用<class>標籤對映成資料庫表,通過<property>標籤將普通屬性對映成表欄位
所謂普通屬性指不包括自定義類、集合和陣列等

注意:如果實體類和實體類中的屬性和sql中的關鍵字重複,必須採用table或column重新命名

實體類的設計原則:
 * 實現一個預設的(即無引數的)構造方法(constructor)
 * 提供一個標識屬性(identifier property)(可選)
 * 使用非final的類 (可選)
 * 為持久化欄位宣告訪問器(accessors) 

主鍵生成策略:
 uuid、native和assigned


4-hibernate多對一關聯對映


關聯對映的本質:
 * 將關聯關係對映到資料庫,所謂的關聯關係是物件模型在記憶體中的一個或多個引用

<many-to-one>會在多的一端加入一個外來鍵,指向一的一端,這個外來鍵是由<many-to-one>
中的column屬性定義的,如果忽略了這個屬性那麼預設的外來鍵與實體的屬性一致

<many-to-one>標籤的定義示例:
  * <many-to-one name="group" column="groupid"/>
 
理解級聯的含義?
 * 是物件的連鎖操作 
   <many-to-one name="group" column="groupid" cascade="all"/>


5-hibernate一對一關聯對映

hibernate一對一主鍵關聯對映(單項關聯Persoon -- > IdCard)

一對一主鍵關聯對映:讓兩個實體物件的id保持相同,這樣可以避免多餘的欄位被建立

具體對映:

<id name="id">
       <!-- person的主鍵來源idCard, 也就是共享idCard的主鍵 -->
       <generator class="foreign">
                   <param  name="property">idCard</param>
        </generator>
</id>
<property name="name"/>
<!--
one-to-one標籤的含義, 指示hibernate怎麼載入它的關聯物件,預設根據主鍵載入,
constrained="true", 表明當前主鍵上存在一個約束,person的主鍵作為外來鍵參照了idCard
-->
<one-to-one name="idCard" constrained="true" />

 

hibernate一對一主鍵關聯對映(雙向關聯Person<---->IdCard)

需要在idcard對映檔案中加入<one-to-one>標籤指向person,指示hibernate如何載入person
預設根據主鍵載入

 

hibernate一對一唯一外來鍵關聯對映(單向關聯Person---->IdCard)

一對唯一外來鍵關聯對映是多對一關聯對映的特例

可以採用<many-to-one>標籤,指定多的一端的unique=true,這樣就限制了多的一端的多重性為一
通過這種手段對映一對一唯一外來鍵關聯

hibernate一對一唯一外來鍵關聯對映(雙向關聯Person<---->IdCard)

一對一唯一外來鍵關聯雙向,需要在另一端(idcard),新增<one-to-one>標籤,指示hibernate如何載入
其關聯物件,預設根據主鍵載入person,外來鍵關聯對映中,因為兩個實體採用的是person的外來鍵維護的關係,
所以不能指定主鍵載入person,而要根據person的外來鍵載入,所以採用如下對映方式:
<one-to-one name="person" property-ref="idCard"/>

 

6-session-flush測試

session flush方法主要做了兩件事:
 * 清理快取
 * 執行sql
 
session在什麼情況下執行flush
 * 預設在事務提交時
 * 顯示的呼叫flush
 * 在執行查詢前,如:iterate
 
hibernate按照save(insert),update、delete順序提交相關操作 


7-hihernate一對多關聯對映

 

(單向Classes----->Student)

一對多關聯對映利用了多對一關聯對映原理

多對一關聯對映:在多的一端加入一個外來鍵指向一的一端,它維護的關係是多指向一
一對多關聯對映:在多的一端加入一個外來鍵指向一的一端,它維護的關係是一指向多

也就是說一對多和多對一的對映策略是一樣的,只是站的角度不同

在一一端維護關係的缺點:
 * 如果將t_student表裡的classesid欄位設定為非空,則無法儲存
 * 因為不是在student這一端維護關係,所以student不知道是哪個班的,
   所以需要發出多餘的update語句來更新關係

 

(雙向Classes<----->Student)

一對多雙向關聯對映:
 * 在一一端的集合上使用<key>,在對方表中加入一個外來鍵指向一一端
 * 在多一端採用<many-to-one>
 
注意:<key>標籤指定的外來鍵欄位必須和<many-to-one>指定的外來鍵欄位一致,否則引用欄位的錯誤
 
如果在”一“一端維護一對多關聯關係,hibernate會發出多餘的udpate語句,所以我們一般在多
的一端來維護關聯關係

關於inverse屬性:
 inverse主要用在一對多和多對多雙向關聯上,inverse可以被設定到集合標籤<set>上,
 預設inverse為false,所以我們可以從”一“一端和”多“一端維護關聯關係,
 如果設定成inverse為true,則我們只能從多一端來維護關聯關係
 
 注意:inverse屬性,隻影響資料的儲存,也就是持久化
  
inverse和cascade
 * inverse是關聯關係的控制方向
 * cascade操作上的連鎖反應

 

 <class name="Classes" >
  <id name="id">
   <generator class="uuid" />
  </id>
  <property name="name"/>
  <set name="students" inverse="true" cascade="all">
   <key column="classesid"/>
   <one-to-many class="Student"/>
  </set>
 </class>

 

 <class name="Student" >
  <id name="id">
   <generator class="uuid" />
  </id>
  <property name="name"/>
  <many-to-one name="classes" column="classesid"/>
 </class>

 

package com.wang.vo;

import java.util.Set;

public class Classes {
 private String id;
 private String name;
 private Set students;
 public String getId() {
  return id;
 }
 public void setId(String 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;
 }
}

public class Student {
 private String id;
 private String name;
 private Classes classes;
 public String getId() {
  return id;
 }
 public void setId(String id) {
  this.id = id;
 }
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public Classes getClasses() {
  return classes;
 }
 public void setClasses(Classes classes) {
  this.classes = classes;
 }
}


8-hibernate多對多關聯對映

hibernate多對多關聯對映(單向User---->Role)

具體對映方式:
 <set name="roles" table="t_user_role">
  <key column="userid"/>
  <many-to-many class="com.wang.hibernate.Role" column="roleid"/>
 </set>

 

hibernate多對多關聯對映(雙向User<---->Role)

對映方法:
  <set name="roles" table="t_user_role">
   <key column="userid"/>
   <many-to-many class="com.wang.hibernate.Role" column="roleid"/>
  </set>
table屬性值必須和單向關聯中的table屬性值一致
<key>中column屬性值要與單向關聯中的<many-to-many>標籤中的column屬性值一致
在<many-to-many>中的column屬性值要與單向關聯中<key>標籤的column屬性值一致


9-hibernate-lazy策略

hibernate-lazy策略可以使用在:
 * <class>標籤上,可以取值:true/false
 * <property>標籤上,可以取值:true/false需要類增強工具
 * <set><list>標籤上,可以取值:true/false/extra
 * <one-to-one><many-to-one>單端關聯上,可以取值:false/proxy/noproxy
 
lazy概念:只有真正使用該物件時,才會建立,對於hibernate而言,正真使用的時候才會發出sql

hibernate支援lazy策略只有在session開啟狀態下有效

<class>標籤上的lazy特性只對普通屬性起作用

 

hibernate在集合上的lazy策略,可以取值:true/false/extra   (設定成extra會調優)

<class>標籤上的lazy不會影響到集合上的lazy特性

 

hibernate在單端關聯上的lazy策略,可以取值:false/proxy/noproxy

<class>標籤上的lazy不會影響到單端關聯上的lazy特性


9-hibernate繼承對映

每棵繼承樹對映成一張表

1、理解如何對映
  因為類繼承樹肯定是對應多個類,要把多個類的資訊存放在一張表中,必須有某種機制來區分哪些記錄是屬於哪個類的。
 這種機制就是,在表中新增一個欄位,用這個欄位的值來進行區分。用hibernate實現這種策略的時候,有如下步驟:
 父類用普通的<class>標籤定義
 在父類中定義一個discriminator,即指定這個區分的欄位的名稱和型別
 如:<discriminator column=”XXX” type=”string”/>
 子類使用<subclass>標籤定義,在定義subclass的時候,需要注意如下幾點:
 Subclass標籤的name屬性是子類的全路徑名
 在Subclass標籤中,用discriminator-value屬性來標明本子類的discriminator欄位(用來區分不同類的欄位)
 的值Subclass標籤,既可以被class標籤所包含(這種包含關係正是表明了類之間的繼承關係),也可以與class標
 籤平行。 當subclass標籤的定義與class標籤平行的時候,需要在subclass標籤中,新增extends屬性,裡面的值
 是父類的全路徑名稱。子類的其它屬性,像普通類一樣,定義在subclass標籤的內部。

2、理解如何儲存
 儲存的時候hibernate會自動將鑑別欄位值插入到資料庫中,在載入資料的時候,hibernate能根據這個鑑別值
 正確的載入物件
 
多型查詢:在hibernate載入資料的時候能鑑別出正真的型別(instanceOf)

get支援多型查詢
load只有在lazy=false,才支援多型查詢
hql支援多型查詢



 


相關文章