1. 程式人生 > >Hibernate之二 一級快取(session)、二級快取(sessionFactory)

Hibernate之二 一級快取(session)、二級快取(sessionFactory)

一、操作Session快取

(1)flush

Session 按照快取中物件的屬性變化來同步更新資料庫

1)預設情況下 Session 在以下時間點重新整理快取:

顯式呼叫 Session 的 flush() 方法

當應用程式呼叫 Transaction 的 commit()方法的時, 該方法先 flush ,然後在向資料庫提交事務

當應用程式執行一些查詢(HQL, Criteria)操作時,如果快取中持久化物件的屬性已經發生了變化,會先 flush 快取,以保證查詢結果能夠反映持久化物件的最新狀態

2)flush 快取的例外情況: 如果物件使用 native 生成器生成 OID, 那麼當呼叫 Session 的 save() 方法儲存物件時, 會立即執行向資料庫插入該實體的 insert 語句.

3)commit() 和 flush() 方法的區別:flush 執行一系列 sql 語句,但不提交事務;commit 方法先呼叫flush() 方法,然後提交事務. 意味著提交事務意味著對資料庫操作永久儲存下來。

4)若希望改變 flush 的預設時間點, 可以通過 Session 的 setFlushMode() 方法顯式設定 flush 的時間點 


(2)refresh

會強制傳送 SELECT 語句, 以使 Session 快取中物件的狀態和資料表中對應的記錄保持一致!

進行一次查詢後,由於session快取,第二次查詢時,將不再發送SQl語句,但是如果呼叫的refresh方法,則強制傳送sql語句進行查詢。

<span style="font-size:14px;">		News news = (News) session.get(News.class, 1);
		System.out.println(news);
		
		session.refresh(news); 
		System.out.println(news); </span>


(3)clear

清理快取

<span style="font-size:14px;">		News news1 = (News) session.get(News.class, 1);
		
		session.clear();
		
		News news2 = (News) session.get(News.class, 1);</span>


二、持久化物件的狀態


臨時物件(Transient): 

在使用代理主鍵的情況下, OID 通常為 null

不處於 Session 的快取中

在資料庫中沒有對應的記錄

持久化物件(也叫”託管”)(Persist):

OID 不為 null

位於 Session 快取中

若在資料庫中已經有和其對應的記錄, 持久化物件和資料庫中的相關記錄對應

Session 在 flush 快取時, 會根據持久化物件的屬性變化, 來同步更新資料庫

在同一個 Session 例項的快取中, 資料庫表中的每條記錄只對應唯一的持久化物件

刪除物件(Removed)

在資料庫中沒有和其 OID 對應的記錄

不再處於 Session 快取中

一般情況下, 應用程式不該再使用被刪除的物件

遊離物件(也叫”脫管”) (Detached):

OID 不為 null

不再處於 Session 快取中

一般情況需下, 遊離物件是由持久化物件轉變過來的, 因此在資料庫中可能還存在與它對應的記錄

(1)save()

Session 的 save() 方法使一個臨時物件轉變為持久化物件

Session 的 save() 方法完成以下操作:

把 News 物件加入到 Session 快取中, 使它進入持久化狀態

選用對映檔案指定的識別符號生成器, 為持久化物件分配唯一的 OID. 在 使用代理主鍵的情況下, setId() 方法為 News 物件設定 OID 使無效的.

計劃執行一條 insert 語句:在 flush 快取的時候

Hibernate 通過持久化物件的 OID 來維持它和資料庫相關記錄的對應關係. 當 News 物件處於持久化狀態時, 不允許程式隨意修改它的 ID

persist() 和 save() 區別:

當對一個 OID 不為 Null 的物件執行 save() 方法時, 會把該物件以一個新的 oid 儲存到資料庫中;  但執行 persist() 方法時會丟擲一個異常.

(2)get() 和 load()

都可以根據跟定的 OID 從資料庫中載入一個持久化物件

當資料庫中不存在與 OID 對應的記錄時

 load() 方法丟擲 ObjectNotFoundException 異常

 get() 方法返回 null

兩者採用不同的延遲檢索策略:load 方法支援延遲載入策略。而 get 不支援。

(3)update()

Session 的 update() 方法使一個遊離物件轉變為持久化物件, 並且計劃執行一條 update 語句.

若希望 Session 僅當修改了 News 物件的屬性時, 才執行 update() 語句, 可以把對映檔案中 <class> 元素的 select-before-update 設為 true. 該屬性的預設值為 false

當 update() 方法關聯一個遊離物件時, 如果在 Session 的快取中已經存在相同 OID 的持久化物件, 會丟擲異常

當 update() 方法關聯一個遊離物件時, 如果在資料庫中不存在相應的記錄, 也會丟擲異常. 

(4)saveOrUpdate()

首先判斷儲存的物件是臨時物件還是遊離物件,若為臨時物件,則呼叫save()方法,若是遊離物件,則呼叫update()方法。

判定物件為臨時物件的標準

  • Java 物件的 OID 為 null
  • 對映檔案中為 <id> 設定了 unsaved-value  屬性, 並且 Java 物件的 OID 取值與這個 unsaved-value 屬性值匹配

(5)delete()

Session 的 delete() 方法既可以刪除一個遊離物件, 也可以刪除一個持久化物件

Session 的 delete() 方法處理過程

計劃執行一條 delete 語句

把物件從 Session 快取中刪除, 該物件進入刪除狀態.

Hibernate 的 cfg.xml 配置檔案中有一個 hibernate.use_identifier_rollback 屬性, 其預設值為 false, 若把它設為 true, 將改變 delete() 方法的執行行為: delete() 方法會把持久化物件或遊離物件的 OID 設定為 null, 使它們變為臨時物件

二、二級快取

1. 加入二級快取外掛EHCache的 jar 包及配置檔案:

I. EHCache依賴的jar包

ehcache-core-2.4.3.jar

hibernate-ehcache-4.2.4.Final.jar

slf4j-api-1.6.1.jar



II. EHCache的配置檔案複製到src下 ehcache.xml

<ehcache>

    <!-- Sets the path to the directory where cache .data files are created.

         If the path is a Java System Property it is replaced by
         its value in the running VM.

         The following properties are translated:
         user.home - User's home directory
         user.dir - User's current working directory
         java.io.tmpdir - Default temp file path -->
    <!--  
    	指定一個目錄:當 EHCache 把資料寫到硬碟上時, 將把資料寫到這個目錄下.
    -->     
    <diskStore path="d:\\tempDirectory"/>


    <!--Default Cache configuration. These will applied to caches programmatically created through
        the CacheManager.

        The following attributes are required for defaultCache:

        maxInMemory       - Sets the maximum number of objects that will be created in memory
        eternal           - Sets whether elements are eternal. If eternal,  timeouts are ignored and the element
                            is never expired.
        timeToIdleSeconds - Sets the time to idle for an element before it expires. Is only used
                            if the element is not eternal. Idle time is now - last accessed time
        timeToLiveSeconds - Sets the time to live for an element before it expires. Is only used
                            if the element is not eternal. TTL is now - creation time
        overflowToDisk    - Sets whether elements can overflow to disk when the in-memory cache
                            has reached the maxInMemory limit.

        -->
    <!--  
    	設定快取的預設資料過期策略 
    -->    
    <defaultCache
        maxElementsInMemory="10000"
        eternal="false"
        timeToIdleSeconds="120"
        timeToLiveSeconds="120"
        overflowToDisk="true"
        />

   	<!--  
   		設定具體的命名快取的資料過期策略。每個命名快取代表一個快取區域
   		快取區域(region):一個具有名稱的快取塊,可以給每一個快取塊設定不同的快取策略。
   		如果沒有設定任何的快取區域,則所有被快取的物件,都將使用預設的快取策略。即:<defaultCache.../>
   		Hibernate 在不同的快取區域儲存不同的類/集合。
			對於類而言,區域的名稱是類名。如:com.atguigu.domain.Customer
			對於集合而言,區域的名稱是類名加屬性名。如com.atguigu.domain.Customer.orders
   	-->
   	<!--  
   		name: 設定快取的名字,它的取值為類的全限定名或類的集合的名字 
		maxElementsInMemory: 設定基於記憶體的快取中可存放的物件最大數目 
		
		eternal: 設定物件是否為永久的, true表示永不過期,
		此時將忽略timeToIdleSeconds 和 timeToLiveSeconds屬性; 預設值是false 
		timeToIdleSeconds:設定物件空閒最長時間,以秒為單位, 超過這個時間,物件過期。
		當物件過期時,EHCache會把它從快取中清除。如果此值為0,表示物件可以無限期地處於空閒狀態。 
		timeToLiveSeconds:設定物件生存最長時間,超過這個時間,物件過期。
		如果此值為0,表示物件可以無限期地存在於快取中. 該屬性值必須大於或等於 timeToIdleSeconds 屬性值 
		
		overflowToDisk:設定基於記憶體的快取中的物件數目達到上限後,是否把溢位的物件寫到基於硬碟的快取中 
   	-->
    <cache name="com.atguigu.hibernate.entities.Employee"
        maxElementsInMemory="1"
        eternal="false"
        timeToIdleSeconds="300"
        timeToLiveSeconds="600"
        overflowToDisk="true"
        />

    <cache name="com.atguigu.hibernate.entities.Department.emps"
        maxElementsInMemory="1000"
        eternal="true"
        timeToIdleSeconds="0"
        timeToLiveSeconds="0"
        overflowToDisk="false"
        />

</ehcache>

2.在hibernate.cfg.xml檔案中進行配置

I.   配置啟用 hibernate 的二級快取

<property name="cache.use_second_level_cache">true</property>

II.  配置hibernate二級快取使用的產品
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

III. 配置對哪些類使用 hibernate 的二級快取
<class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>

3. 集合級別的二級快取的配置

I. 配置對集合使用二級快取 hibernate.hbm.xml

<collection-cache usage="read-write" collection="com.atguigu.hibernate.entities.Department.emps"/>

也可以在 .hbm.xml 檔案中進行配置

<set name="emps" table="GG_EMPLOYEE" inverse="true" lazy="true">
	<cache usage="read-write"/>
    <key>
        <column name="DEPT_ID" />
    </key>
    <one-to-many class="com.atguigu.hibernate.entities.Employee" />
</set>
II. 注意: 還需要配置集合中的元素對應的持久化類也使用二級快取! 否則將會多出 n 條 SQL 語句. 
<class-cache usage="read-write" class="com.atguigu.hibernate.entities.Employee"/>