hibernate session緩存
Session 概述
Session 接口是 Hibernate 向應用程序提供的操縱數據庫的最基本的接口, 它提供了基本的保存, 更新, 刪除和載入 Java 對象的方法.
Session 具有一個緩存, 位於緩存中的對象稱為持久化對象, 它和數據庫中的相關記錄相應. Session 可以在某些時間點, 依照緩存中對象的變化來運行相關的 SQL 語句, 來同步更新數據庫, 這一過程被稱為刷新緩存(flush)
站在持久化的角度, Hibernate 把對象分為 4 種狀態: 持久化狀態, 暫時狀態, 遊離狀態, 刪除狀態. Session 的特定方法能使對象從一個狀態轉換到還有一個狀態.
Session 緩存
在 Session 接口的實現中包括一系列的 Java 集合, 這些 Java 集合構成了 Session 緩存. 僅僅要 Session 實例沒有結束生命周期, 且沒有清理緩存。則存放在它緩存中的對象也不會結束生命周期
Session 緩存可降低 Hibernate 應用程序訪問數據庫的頻率。
操作 Session 緩存
flush()
flush:使數據庫表中的記錄和session緩存中的對象的狀態保持一致。為了保持一致。則可能會發送相應的sql語句。
默認情況下 Session 在下面時間點刷新緩存:
顯式調用 Session 的 flush() 方法,可能會發送sql語句(為什麽使用可能,由於查詢得到數據庫中的狀態與當前對象狀態一致則不會發送sql更新),但不會提交事務(發送了sql語句。必須提交事務才會更新數據庫)
當應用程序調用 Transaction 的 commit()方法的時, 該方法先 flush(更新) ,然後在向數據庫提交事務
當應用程序運行一些查詢(HQL, Criteria)操作時,假設緩存中持久化對象的屬性已經發生了變化。會先 flush 緩存。以保證查詢結果可以反映持久化對象的最新狀態(當然這樣的情況也僅僅是在事務範圍內更新了,還未同步到數據庫。僅僅有提交事務才會更新到數據庫)
flush 緩存的例外情況: 假設對象使用 native 生成器生成 OID(記錄的id是由底層數據庫使用自增生成的), 那麽當調用 Session 的 save() 方法保存對象時, 會馬上運行向數據庫插入該實體的 insert 語句同步到數據庫.由於save方法後必須保證id是存在的。(假設id是由hibernate生成則才是在commit提交事務時才發送insert同步到數據庫)
commit() 和 flush() 方法的差別:flush 運行一系列 sql 語句,但不提交事務;commit 方法先調用flush() 方法,然後提交事務. 意味著提交事務意味著對數據庫操作永久保存下來。
設定刷新緩存的時間點(了解就可以。通常不會去更改)
若希望改變 flush 的默認時間點, 能夠通過 Session 的 setFlushMode() 方法顯式設定 flush 的時間點
refresh()
會強制發送select語句,以使session緩存中對象的狀態和數據庫表中的相應的記錄保持一致。受數據庫隔離級別控制。
(必須了解數據庫隔離級別,例如以下所看到的)
數據庫的隔離級別
對於同一時候執行的多個事務, 當這些事務訪問數據庫中同樣的數據時, 假設沒有採取必要的隔離機制, 就會導致各種並發問題:
臟讀: 對於兩個事物 T1, T2, T1 讀取了已經被 T2 更新但還沒有被提交的字段. 之後, 若 T2 回滾, T1讀取的內容就是暫時且無效的.
不可反復讀: 對於兩個事物 T1, T2, T1 讀取了一個字段, 然後 T2 更新了該字段. 之後, T1再次讀取同一個字段, 值就不同了.
幻讀: 對於兩個事物 T1, T2, T1 從一個表中讀取了一個字段, 然後 T2 在該表中插入了一些新的行. 之後, 假設 T1 再次讀取同一個表, 就會多出幾行.
數據庫事務的隔離性: 數據庫系統必須具有隔離並發執行各個事務的能力, 使它們不會相互影響, 避免各種並發問題.
一個事務與其它事務隔離的程度稱為隔離級別. 數據庫規定了多種事務隔離級別, 不同隔離級別相應不同的幹擾程度, 隔離級別越高, 數據一致性就越好, 但並發性越弱數據庫提供的 4 種事務隔離級別:
Oracle 支持的 2 種事務隔離級別:READ COMMITED, SERIALIZABLE. Oracle 默認的事務隔離級別為: READ COMMITED
Mysql 支持 4 中事務隔離級別. Mysql 默認的事務隔離級別為: REPEATABLE READ在 MySql 中設置隔離級別
- 每啟動一個 mysql 程序, 就會獲得一個單獨的數據庫連接. 每一個數據庫連接都有一個全局變量 @@tx_isolation, 表示當前的事務隔離級別. MySQL 默認的隔離級別為 Repeatable Read
-
查看當前的隔離級別: SELECT @@tx_isolation;
-
設置當前 mySQL 連接的隔離級別:
set transaction isolation level read committed;
-
設置數據庫系統的全局的隔離級別:
set global transaction isolation level read committed;
在 Hibernate 中設置隔離級別
- JDBC數據庫連接使用數據庫系統默認的隔離級別.在Hibernate的配置文件裏能夠顯式的設置隔離級別.每個隔離級別都相應一個整數: –1.READ UNCOMMITED –2.READ COMMITED –4.REPEATABLE READ –8.SERIALIZEABLE
-
Hibernate通過為Hibernate映射文件指定hibernate.connection.isolation屬性來設置事務的隔離級別
clear()
清理緩存
hibernate session緩存