hibernate相關知識

hibernate多對一關聯映射
關聯映射的本質:將關聯關係映射到數據庫,關聯關係在對象模型域中體現爲一個或多個引用

<many-to-one>標籤會在“多”的一端添加一個外鍵,指向“一”的一端,這個外鍵是由<many-to-one>
中的column的屬性定義的,如果忽略這個屬性,默認創建的外鍵與實體類的屬性名相同

<many-to-one>定義示例:
* <many-to-one name="group" column="groupid"/>

理解cascade
* 是對象之間的連鎖操作(只對增刪改起作用)
hibernate一對一主鍵關聯映射(單項關聯)
hibernate一對一主鍵關聯映射(單項關聯)Person--->IdCard

主鍵關聯映射:讓兩個對象的id保持相同,這樣可以避免多餘的字段被創建

<one-to-one>標籤指示hibernate如何加載其引用對象,缺省情況下根據主鍵加載其引用對象

<id name="id">
<generator class="foreign">
<!-- person中的id來源於idCard,即共享idCard主鍵 -->
<param name="property">idCard</param>
</generator>
</id>
<property name="name"/>
<!-- constrained="true",當前主鍵上存在一個約束,表明person中的主鍵作爲外鍵參照了idCard -->
<one-to-one name="idCard" constrained="true"/>
hibernate一對一主鍵關聯映射(雙項關聯)
hibernate一對一主鍵關聯映射(雙項關聯)Person<--->IdCard

需要在idCard加入<one-to-one>標籤,指示hibernate如何加載person,默認情況下根據主鍵加載

<one-to-one name="person"></one-to-one>
hibernate一對一唯一外鍵關聯映射(單項關聯)
hibernate一對一唯一外鍵關聯映射(單項關聯)Person--->IdCard

一對一唯一外鍵關聯實際上是多對一關聯映射的特例

可以採用<many-to-one>標籤,指定“多”的一端unique=“true”,即限制了“多”一端的多重性爲“一”
這樣就構成了一對一唯一外鍵關聯映射
hibernate一對一唯一外鍵關聯映射(雙向關聯)
hibernate一對一唯一外鍵關聯映射(雙向關聯)Person<--->IdCard

一對一唯一外鍵雙向關聯映射,需要在另一端(IdCard),添加<one-to-one>標籤,指示hibernate如何
加載其引用對象,默認情況下根據主鍵加載person,因爲外鍵關聯映射中,兩個實體的關係是由person的
外鍵IdCard維護的,所以不能指定person的主鍵來加載person,而是根據person的外鍵idCard來加載person
對象,如:
<one-to-one name="person" property-ref="idCard"></one-to-one>

hibernate一對多關聯映射(單向關聯)
hibernate一對多關聯映射(單向關聯)Classes--->Student

這種關聯映射的原理採用的是多對一關聯映射的原理

多對一關聯映射,是在“多”的一端添加一個外鍵指向“一”的一端,它維護的關係多到一的關係
一對多關聯應是,是在“多”的一端添加一個外鍵指向“一”的一端,它維護的關係一到多的關係

也就是說,一對多和多對一關聯映射的策略是一致的,只是站的角度不同

缺點:
* 更新student表中的classesid字段時,會發出多餘的update語句,來維護classes到student之間的關係
* 如果將t_student中的classesid設置爲非空,則不能成功保存

<set name="students" order-by="id">
<!--
<key column="classesid" not-null="true"></key>
-->
<key column="classesid"></key>
<one-to-many class="com.bjsxt.hibernate.Student"/>
</set>
hibernate一對多關聯映射(雙向關聯)
hibernate一對多關聯映射(雙向關聯)Classes<--->Student

一對多雙向關聯映射的方法:
* 在“一”一端的集合中使用<key>標籤,在對方表中加入一個外鍵指向“一”一端
* 在“多"的一端採用<many-to-one>

注意:<key>標籤指定的外鍵字段必須和<many-to-one>指定的外鍵字段一致,否則引起字段錯誤
<many-to-one name="classes" column="classesid" cascade="all"></many-to-one>

如果在“一”一端維護一對多關聯關係,hibernate會發出多餘的update語句,所以我們一般在多的一端來維護關聯關係。

關於inverse屬性:
inverse主要用在一對多和多對多雙向關聯上,inverse可以被是知道集合標籤<set>上,默認inverse爲false,
所以我們可以從“一”一端和“多”一端維護關聯關係,如果設置成inverse爲true,則我們只能從多一端來維護關聯關係。

注意:inverse屬性,隻影響數據的存儲,也就是持久化

inverse和cascade
* inverse是關聯關係的控制方向
* cascade是指操作上的連鎖反映
hibernate多對多關聯映射(單項關聯)
hibernate多對多關聯映射(單項關聯)user--->role

映射規則:
<set name="roles" table="t_user_role">
<key column="userid"></key>
<many-to-many class="com.bjsxt.hibernate.Role" column="roleid"/>
</set>
hibernate多對多關聯映射(雙項關聯)
hibernate多對多關聯映射(雙項關聯)user<--->role

映射規則:

Java代碼  收藏代碼
  1. <set name="users" table="t_user_role" order-by="userid">  

  2. <key column="roleid"/>  

  3. <many-to-many class="com.bjsxt.hibernate.User" column="userid"></many-to-many>  

  4. </set>  


* table屬性值必須和單向關聯中的table屬性值一致
* <key>標籤中的column屬性值必須和單向關聯中的<many-to-many>中的column屬性值一致
* <many-to-many>標籤中的column必須和單向關聯中的<key>標籤中的column屬性值一致
基本映射說明
基本映射

類-->數據庫表

普通屬性-->表字段

通過<class>映射到數據庫表,通過<property>將普通屬性映射到表字段。
所謂普通屬性不包擴,自定義類,集合,數組

實體類主要設計原則:
* 實現一個默認的(即無參數的)構造方法(constructor)
* 提供一個標識屬性(identifier property)(可選)
* 使用非final的類(可選)
* 爲持久化字段聲明訪問器(accessors)(可選)

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

id的映射:
瞭解uuid、native和assigned

注意:類的名稱和類中屬性的名稱,如果和sql中的關鍵字重複,必須用table或column屬性重命名
hibernate的session.flush
測試session.flush

1、session在什麼情況下清理緩存:
* 默認情況下,當應用程序提交事務,如:Transaction.commit;
* 當我們顯示調用flush的時候
* 在執行某些查詢的時候,如:iterate

2、session.flush()主要完成兩件事情:
* 清理緩存
* 執行sql

3、flush執行的順序:hibernate按照save,update,delete順序提交相關操作
Hibernate的一個配置參數hibernate.hbm2ddl.auto
關鍵字: hibernate hbm2ddl.auto
Java代碼  
1.<properties>  
2.           <property name="hibernate.show_sql" value="true" />        
3.           <property name="hibernate.hbm2ddl.auto" value="create" />  
4.</properties>  

看到了嗎?
hibernate.hbm2ddl.auto value=“create”
看一下hibernate的官方解釋:
hibernate.hbm2ddl.auto Automatically validate or export schema DDL to the database when the SessionFactory is created. With create-drop, the database schema will be dropped when the SessionFactory is closed explicitly. eg. validate | update | create | create-drop
有意思吧~!
竟然可以自動創建|更新|驗證數據庫表結構。
呵呵 不過如果不是此方面的需求建議set value="none".
下面是這幾個屬性的解釋:
validate               加載hibernate時,驗證創建數據庫表結構
create                  每次加載hibernate,重新創建數據庫表結構,這就是導致數據庫表數據丟失的原因。
create-drop         加載hibernate時創建,退出是刪除表結構
update                加載hibernate自動更新數據庫結構

1.請慎重使用此參數,沒必要就不要隨便用。如果要用盡量使用update
2.如果發現數據庫表丟失,請檢查hibernate.hbm2ddl.auto的配置

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策略可以使用在:
* <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特性只對普通屬性起作用
重要的概念:
1、lazy的概念,指在需要的時候才發出sql
2、lazy策略只是在session打開期間纔是有效的

注意:
Hibernate類級別的lazy加載策略:可以控制什麼時候加載這些普通對象屬性

測試單元的使用:
請先運行初時化程序InitData,在執行每個單元測試


Hibernate集合屬性的懶加載策略:

在集合屬性上,可以配置懶加載策略,取值爲:true/false/extra

true:默認取值,它的意思是只有在調用這個集合獲取裏面的元素對象時,才發出查詢語句,加載其
    集合元素的數據
false:取消懶加載特性,即在加載對象的同時,就發出第二條查詢語句加載其關聯集合的數據
extra:一種比較聰明的懶加載策略,即調用集合的size/contains等方法的時候,hibernate並不會去加載整個集合的數據,而是發出一條聰明的SQL語句,以便獲得需要的值,只有在真正需要用到這些集合元素對象數據的時候,纔去發出查詢語句加載所有對象的數據


Hibernate單端關聯懶加載策略:即在<one-to-one>/<many-to-one>標籤上可以配置
懶加載策略。

可以取值爲:false/proxy/no-proxy
false:取消懶加載策略,即在加載對象的同時,發出查詢語句,加載其關聯對象
proxy:這是hibernate對單端關聯的默認懶加載策略,即只有在調用到其關聯對象的方法的時候
     才真正發出查詢語句查詢其對象數據,其關聯對象是代理類
no-proxy:這種懶加載特性需要對類進行增強,使用no-proxy,其關聯對象不是代理類

注意:在class標籤上配置的lazy屬性不會影響到關聯對象!!!

hibernate的lazy策略forClass
lazy策略可以用在:
* <class>標籤上,可以取值:true/false
* <property>標籤上,可以取值:true/false,這個特性需要類增強工具
* <set><list>等集合上,可以取值:true/false/extra
* <one-to-one>和<many-to-many>(單端關聯)等標籤上,可以取值:false/proxy/noproxy

概念:
1、lazy是隻有需要的時候才發出sql語句
2、hibernate支持lazy策略,只有session打開狀態下才有效

hibernate類級別的lazy測試,可以控制什麼時候加載這些普通屬性
把class的lazy設置成false時,再load類時會把普通屬性都查出來,但是集合不查
class標籤上的lazy不會影響到集合上的lazy特性
class標籤上的lazy特性只對普通屬性起作用

使用:
1、運行initData
2、運行測試用例
hibernate在集合上的lazy策略
hibernate在集合上的lazy策略,可以取值true/false/extra
測試集合lazy:
get集合時不會發sql,迭代會發sql
查個數的時候會把整個集合查出來,這樣的話對效率有影響
lazy在集合上用extra在獲取size的時候會發出count語句,這樣對效率有提升

使用:
1、運行InitData
2、運行測試用例
hibernate在單端關聯上的lazy策略
hibernate在單端關聯上的lazy策略,<one-to-one>和<many-to-one>,可以取值:false/proxy/noproxy
在單端關聯上lazy默認,和集合一樣,在get時返回代理不發查詢語句,在使用時發出sql
在單端關聯上lazy=false,在訪問普通屬性時發出兩條sql,查詢屬性以及對應的關聯對象
將class標籤上lazy設置成false,其它默認:
不會影響單端關聯,也不會影響集合

使用:
1、運行InitData
2、運行測試用例

Hibernate中的繼承映射
Hibernate的繼承映射包含了三種不同的策略:
1.每棵繼承樹映射成一張表
2.每個子類映射成一張表;
3.每個具體類映射成一張表(有限制)。
每棵繼承樹映射成一張表



每棵繼承樹映射成一張表
t_animal
idnameSexweightheighttype
1豬豬True100P
2鳥鳥False50B


Java代碼  收藏代碼
  1. Animal.java  

  2. publicclass Animal {  

  3. privateint id;  

  4. private String name;  

  5. privateboolean sex;  

  6. getter and setter; }  

  7. Pig.java  

  8. publicclass Pig extends Animal {  

  9. privateint weight;  

  10.    getter and setter;  

  11. }  

Java代碼  收藏代碼
  1. Bird.java  

  2. publicclass Bird extends Animal {  

  3. privateint height;  

  4.    getter and setter;  

  5. }  

Java代碼  收藏代碼
  1. Extend.hbm.xml  

  2. <hibernate-mapping package="com.bjsxt.hibernate">  

  3.    <class name="Animal" table="t_animal" lazy="false">  

  4.        <id name="id">  

  5.            <generator class="native"/>  

  6.        </id>  

  7.        <discriminator column="type" type="string"/>  

  8.        <property name="name"/>  

  9.        <property name="sex"/>  

  10.        <subclass name="Pig" discriminator-value="P">  

  11.            <property name="weight"/>  

  12.        </subclass>  

  13.        <subclass name="Bird" discriminator-value="B">  

  14.            <property name="height"/>  

  15.        </subclass>  

  16.    </class>  

  17. </hibernate-mapping>  


每個子類一個表;(效率不高。實體類跟上面的一樣)
Java代碼  收藏代碼
  1. <hibernate-mapping package="com.bjsxt.hibernate">  

  2.    <class name="Animal" table="t_animal">  

  3.        <id name="id">  

  4.            <generator class="native"/>  

  5.        </id>  

  6.        <property name="name"/>  

  7.        <property name="sex"/>  

  8.        <joined-subclass name="Pig" table="t_pig">  

  9.            <key column="pid"/>  

  10.            <property name="weight"/>  

  11.        </joined-subclass>  

  12.        <joined-subclass name="Bird" table="t_bird">  

  13.            <key column="bid"/>  

  14.            <property name="height"/>  

  15.        </joined-subclass>  

  16.    </class>  

  17. </hibernate-mapping>  

每個具體類映射成一張表(有限制)

每個具體類映射成一張表(主表可以不生成 在class中 設置 abstract = “ true”)
t_pig
idNamesexweight
1豬豬true100
t_bird
idNamesexheight
2鳥鳥false50

session{
map{
key=Animal+id
}
}
(實體類跟上面的一樣) 主鍵不能用自增,主鍵手動設置
Java代碼  收藏代碼
  1. Extends.hbm.xml  

  2. <hibernate-mapping package="com.bjsxt.hibernate">  

  3.    <class name="Animal"abstract="true">  

  4.        <id name="id">  

  5.            <generator class="assigned"/>  

  6.        </id>  

  7.        <property name="name"/>  

  8.        <property name="sex"/>  

  9.        <union-subclass name="Pig" table="t_pig">  

  10.            <property name="weight"/>  

  11.        </union-subclass>  

  12.        <union-subclass name="Bird" table="t_bird">  

  13.            <property name="height"/>  

  14.        </union-subclass>  

  15.    </class>  

  16. </hibernate-mapping>  


component映射(只建一張表)

在hibernate中,component是某個實體的邏輯組成部分,它與實體的根本區別是沒有oid,
component可以成爲是值對象(DDD)

採用component映射的好處:它實現了對象模型的細粒度劃分,層次會更分明,複用率會更高
Java代碼  收藏代碼
  1. Contact.java  

  2. publicclass Contact {  

  3. private String email;  

  4. private String address;  

  5. private String zipCode;  

  6. private String contactTel;  

  7. getter and setter;  

  8. }  

Java代碼  收藏代碼
  1. User.java  

  2. publicclass User {  

  3. privateint id;  

  4. private String name;  

  5. private Contact contact;  

  6.    getter and setter;  

  7. }  

Java代碼  收藏代碼
  1. User.hbm.xml  

  2. <hibernate-mapping>  

  3.    <class name="com.bjsxt.hibernate.User" table="t_user">  

  4.        <id name="id">  

  5.            <generator class="native"/>  

  6.        </id>  

  7.        <property name="name"/>  

  8.        <component name="contact">  

  9.            <property name="email"/>  

  10.            <property name="address"/>  

  11.            <property name="zipCode"/>  

  12.            <property name="contactTel"/>  

  13.        </component>  

  14.    </class>  

  15. </hibernate-mapping>  

複合主鍵映射(單獨建一個實體類,重寫hashCode和equals方法,實現序列化接口)
通常將複合主鍵相關的屬性,單獨放到一個類中
* 此類必須實現序列化接口
* 覆寫hashcode和equals方法

Java代碼  收藏代碼
  1. <hibernate-mapping>  

  2.    <class name="com.bjsxt.hibernate.FiscalYearPeriod" table="t_fiscal_year_period">  

  3.        <composite-id name="fiscalYearPeriodPK">  

  4.            <key-property name="fiscalYear"/>   //第一個主鍵

  5.            <key-property name="fiscalPeriod"/>   //第二個主鍵

  6.        </composite-id>  

  7.        <property name="beginDate"/>  

  8.        <property name="endDate"/>  

  9.        <property name="periodSts"/>  

  10.    </class>  

  11. </hibernate-mapping>  


hibernate-悲觀鎖與樂觀鎖
悲觀鎖

悲觀鎖的實現,通常依賴於數據庫機制,在整個過程中將數據鎖定,其它任何用戶都不能讀取或修改
Java代碼  收藏代碼
  1. Inventory.java  

  2. publicclass Inventory {  

  3. privateint itemNo;  

  4. private String itemName;  

  5. privateint quantity;}  

Java代碼  收藏代碼
  1. <pre name="code"class="java">Inventory.hbm..xml  

  2. <hibernate-mapping>  

  3.    <class name="com.bjsxt.hibernate.Inventory" table="t_inventory">  

  4.        <id name="itemNo">  

  5.            <generator class="native"/>  

  6.        </id>  

  7.        <property name="itemName"/>  

  8.        <property name="quantity"/>  

  9.    </class>  

  10. </hibernate-mapping></pre>操作類中實現:  

  11. <br>    Inventory inv = (Inventory)session.load(Inventory.class, 1, LockMode.UPGRADE);  


Hibernate的加鎖模式有:

LockMode.NONE : 無鎖機制。
LockMode.WRITE :Hibernate在Insert和Update記錄的時候會自動獲取。
LockMode.READ : Hibernate在讀取記錄的時候會自動獲取。

以上這三種鎖機制一般由Hibernate內部使用,如Hibernate爲了保證Update
過程中對象不會被外界修改,會在save方法實現中自動爲目標對象加上WRITE鎖。

LockMode.UPGRADE :利用數據庫的for update子句加鎖。
LockMode. UPGRADE_NOWAIT :Oracle的特定實現,利用Oracle的for update nowait子句實現加鎖。

樂觀鎖
大多數基於數據版本記錄機制(version)實現,一般是在數據庫表中加入一個version字段
讀取數據時將版本號一同讀出,之後更新數據時版本號加一,如果提交數據時版本號小於或等於數據表中
的版本號,則認爲數據是過期的,否則給予更新

Java代碼  收藏代碼
  1. <hibernate-mapping>  

  2.    <class name="Inventory" table="t_inventory" optimistic-lock="version">  

  3.        <id name="itemNo">  

  4.            <generator class="native"/>  

  5.        </id>  

  6.        <version name="version"/>  

  7.        <property name="itemName"/>  

  8.        <property name="quantity"/>  

  9.    </class>  

  10. </hibernate-mapping>  


hibernate查詢語言hql


1、簡單屬性查詢【重要】
* 單一屬性查詢,返回結果集屬性列表,元素類型和實體類中相應的屬性類型一致
* 多個屬性查詢,返回的集合元素是對象數組,數組元素的類型和對應的屬性在實體類中的類型一致
*在hql中關鍵字不區分大小寫,但是屬性和類名區分大小寫


 數組的長度取決與select中屬性的個數
* 如果認爲返回數組不夠對象化,可以採用hql動態實例化Student對象
參見:SimplePropertyQueryTest.java  

2、實體對象查詢【重要】
* N + 1問題,在默認情況下,使用query.iterate查詢,有可以能出現N+1問題
 所謂的N+1是在查詢的時候發出了N+1條sql語句
 1: 首先發出一條查詢對象id列表的sql
 N: 根據id列表到緩存中查詢,如果緩存中不存在與之匹配的數據,那麼會根據id發出相應的sql語句
* list和iterate的區別?
* list每次都會發出sql語句,list會向緩存中放入數據,而不利用緩存中的數據
* iterate:在默認情況下iterate利用緩存數據,但如果緩存中不存在數據有可以能出現N+1問題
參見:SimpleObjectQueryTest1.java/SimpleObjectQueryTest2.java

3、條件查詢【重要】
* 可以採用拼字符串的方式傳遞參數
* 可以採用 ?來傳遞參數(索引從0開始)
* 可以採用 :參數名 來傳遞參數
* 如果傳遞多個參數,可以採用setParamterList方法
* 在hql中可以使用數據庫的函數,如:date_format
參見:SimpleConditionQueryTest.java

4、hibernate也支持直接使用sql進行查詢
參見:SqlQueryTest.java

5、外置命名查詢
* 在映射文件中採用<query>標籤來定義hql
* 在程序中採用session.getNamedQuery()方法得到hql查詢串
參見:Student.hbm.xml、NameQueryTest.java

6、查詢過濾器
* 在映射文件中定義過濾器參數
* 在類的映射中使用這些參數
* 在程序中啓用過濾器
參見:Student.hbm.xml、FilterQueryTest.java

7、分頁查詢【重要】
* setFirstResult(),從0開始
* setMaxResults,每頁顯示多少條數據
參見:PageQueryTest.java

8、對象導航查詢,在hql中採用 . 進行導航【重要】
參見:ObjectNavQueryTest.java

9、連接查詢【重要】
* 內連
* 外連接(左連接/右連接)
參見:JoinQueryTest.java

10、統計查詢【重要】
參見:StatQueryTest.java

11、DML風格的操作(儘量少用,因爲和緩存不同步)
參見:DMLQueryTest.java

hibernate一級緩存

一級緩存很短和session的生命週期一致,一級緩存也叫session級的緩存或事務級緩存

那些方法支持一級緩存:
* get()
* load()
* iterate(查詢實體對象)

如何管理一級緩存:
* session.clear(),session.evict()

如何避免一次性大量的實體數據入庫導致內存溢出
* 先flush,再clear

如果數據量特別大,考慮採用jdbc實現,如果jdbc也不能滿足要求可以考慮採用數據本身的特定導入工具

在同一個session中發出兩次load查詢:
Java代碼  收藏代碼
  1. Student student = (Student)session.load(Student.class, 1);  

  2.            System.out.println("student.name=" + student.getName());  

  3. //不會發出sql,因爲load使用緩存

  4.            student = (Student)session.load(Student.class, 1);  

  5.            System.out.println("student.name=" + student.getName());  



在同一個session中發出兩次get查詢:
Java代碼  收藏代碼
  1. Student student = (Student)session.get(Student.class, 1);  

  2.            System.out.println("student.name=" + student.getName());  

  3. //不會發出sql,因爲get使用緩存

  4.            student = (Student)session.get(Student.class, 1);  

  5.            System.out.println("student.name=" + student.getName());  


在同一個session中發出兩次iterate查詢實體對象:
Java代碼  收藏代碼
  1. Student student =  

  2. (Student)session.createQuery("from Student s where s.id=1").iterate().next();  

  3.            System.out.println("student.name=" + student.getName());  

  4. //會發出查詢id的sql,不會發出查詢實體對象的sql,因爲iterate使用緩存

  5.            student =  

  6. (Student)session.createQuery("from Student s where s.id=1").iterate().next();  

  7.            System.out.println("student.name=" + student.getName());  

在同一個session中發出兩次iterate查詢實體對象:

Java代碼  收藏代碼
  1. String name =  

  2. (String)session.createQuery("select s.name from Student s where s.id=1").iterate().next();  

  3.            System.out.println("student.name=" + name);  

  4. //iterate查詢普通屬性,一級緩存不會緩存,所以發出sql

  5. //一級緩存是緩存實體對象的

  6.            name =  

  7. (String)session.createQuery("select s.name from Student s where s.id=1").iterate().next();  

  8.            System.out.println("student.name=" + name);  

開啓兩個session中發出load查詢:
Session1中:
Java代碼  收藏代碼
  1. session = HibernateUtils.getSession();  

  2.            session.beginTransaction();  

  3.            Student student = (Student)session.load(Student.class, 1);  

  4.            System.out.println("student.name=" + student.getName());  

  5. Session2中:  


Java代碼  收藏代碼
  1. //會發出查詢語句,session間不能共享一級緩存的數據

  2. //因爲它會伴隨session的生命週期存在和消亡

  3.        Student student = (Student)session.load(Student.class, 1);  

  4.        System.out.println("student.name=" + student.getName());  


在同一個session中先save,在發出load查詢save過的數據:

Java代碼  收藏代碼
  1. Student stu = new Student();  

  2.            stu.setName("王五");  

  3.            Serializable id = session.save(stu);  

  4. //不會發出sql,因爲save是使用緩存的

  5.            Student student = (Student)session.load(Student.class, id);  

  6.            System.out.println("student.name=" + student.getName());  


向數據庫中批量加入1000條數據:

Java代碼  收藏代碼
  1. for (int i=0; i<1000; i++) {  

  2.                Student student = new Student();  

  3.                student.setName("s_" + i);  

  4.                session.save(student);  

  5. //每20條數據就強制session將數據持久化

  6. //同時清除緩存,避免大量數據造成內存溢出

  7. if ( i % 20 == 0) {  

  8.                    session.flush();  

  9.                    session.clear();  

  10.                }  

  11.            }  


hibernate二級緩存

二級緩存也稱進程級的緩存或SessionFactory級的緩存,二級緩存可以被所有的session共享
二級緩存的生命週期和SessionFactory的生命週期一致,SessionFactory可以管理二級緩存

二級緩存的配置和使用:
* 將echcache.xml文件拷貝到src下
* 開啓二級緩存,修改hibernate.cfg.xml文件
<property name="hibernate.cache.use_second_level_cache">true</property>
* 指定緩存產品提供商,修改hibernate.cfg.xml文件
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
* 指定那些實體類使用二級緩存(兩種方法)
* 在映射文件中採用<cache>標籤
* 在hibernate.cfg.xml文件中,採用<class-cache>標籤

二級緩存是緩存實體對象的

瞭解一級緩存和二級緩存的交互

Hibernate.cfg.xml
<!-- 開啓二級緩存 -->
<property name="hibernate.cache.use_second_level_cache">true</property>

<!-- 指定緩存產品提供商 -->
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvide
r</property>


hibernate查詢緩存

查詢緩存是針對普通屬性結果集的緩存
對實體對象的結果集只緩存id

查詢緩存的生命週期,當前關聯的表發生修改,那麼查詢緩存生命週期結束

查詢緩存的配置和使用:
* 在hibernate.cfg.xml文件中啓用查詢緩存,如:
<property name="hibernate.cache.use_query_cache">true</property>
* 在程序中必須手動啓用查詢緩存,如:
query.setCacheable(true);

hibernate抓取策略(單端代理的批量抓取)

保持默認,同fetch="select",如:
<many-to-one name="classes" column="classesid" fetch="select"/>

fetch="select",另外發送一條select語句抓取當前對象關聯實體或集合

hibernate抓取策略(單端代理的批量抓取)

設置fetch="join",如:
<many-to-one name="classes" column="classesid" fetch="join"/>

fetch="join",hibernate會通過select語句使用外連接來加載其關聯實體或集合

此時lazy會失效

hibernate抓取策略(集合代理的批量抓取)

保持默認,同fetch="select",如:
<set name="students" inverse="true" cascade="all" fetch="select">

fetch="select",另外發送一條select語句抓取當前對象關聯實體或集合

hibernate抓取策略(集合代理的批量抓取)

設置fetch="join",如:
<set name="students" inverse="true" cascade="all" fetch="join">

fetch="join",hibernate會通過select語句使用外連接來加載其關聯實體或集合

此時lazy會失效

hibernate抓取策略(集合代理的批量抓取)

設置fetch="subselect",如:
<set name="students" inverse="true" cascade="all" fetch="subselect">

fetch="subselect",另外發送一條select語句抓取在前面查詢到的所有實體對象的關聯集合



hibernate抓取策略,,batch-szie在<class>上的應用

batch-size屬性,可以批量加載實體類,參見:Classes.hbm.xml
<class name="Classes" table="t_classes" batch-size="3">

hibernate抓取策略,batch-szie在集合上的應用


batch-size屬性,可以批量加載實體類,參見:Classes.hbm.xml
<set name="students" inverse="true" cascade="all" batch-size="5">


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章