Hibernate本身沒有事務的實現 Hibernate 直接使用 JDBC 串連和 JTA 資源,不添加任何附加鎖定行為。也就是說你在Hibernate裡面使用的事務要麼是JDBC的事務,要麼是JTA的事務。Hibernate不鎖定記憶體中的對象 你的應用程式會按照你的資料庫事務的隔離等級規定的那樣運作,真正對事務的實現和支援也依賴於資料庫。
對於並發處理,Hibernate提供了樂觀鎖和悲觀鎖來進行並發處理Hibernate對自動開放式並行存取控制提供版本管理,針對行級悲觀鎖定,Hibernate 也提供了輔助的(較小的)API,它使用了 SELECT FOR UPDATE 的 SQL 文法Hibernate的Session是和事務聯絡在一起的 可以通過Session去擷取事務的介面,從而進行事務的控制。
資料庫事務應該儘可能的短 這樣能降低資料庫中的鎖爭用。資料庫長事務會阻止你的應用程式擴充到高的並發負載。因此,假若在使用者思考期間讓資料庫事務開著,直到整個工作單元完成才關閉這個事務,這絕不是一個好的設計。這就引出一個問題:一個操作單元,也就是一個事務單元的範圍應該是多大? 一個操作一個?一個請求一個?一個應用一個?
反模式:session-per-operation 在單個線程中, 不要因為一次簡單的資料庫調用,就開啟和關閉一次 Session!資料庫事務也是如此。也就是說應該禁止自動事務提交(auto-commit)。
session-per-request 最常用的模式是 每個請求一個會話。 在這種模式下,來自用戶端的請求被發送到伺服器端,即 Hibernate 持久化層啟動並執行地方,一個新的 Hibernate Session 被開啟,並且執行這個操作單元中所有的資料庫操作。一旦操作完成(同時對用戶端的響應也準備就緒),session 被同步,然後關閉。會話和請求之間的關係是一對一的關係。Hibernate 內建了對“當前 session(current session)” 的管理,用於簡化此模式。你要做的一切就是在伺服器端要處理請求的時候,開啟事務,在響應發送給客戶之前結束事務,通常使用Servelt Filter來完成。
非託管環境下 所謂非託管,指的是:應用程式沒有託管到J2EE環境中,通常由Hibernate自己來負責管理資料庫串連池。應用程式開發人員必須手工設定事務聲明,換句話說,就是手工啟動,提交,或者復原資料庫事務。
使用JTA 又有兩種方式,一種是在Hibernate配置裡面修改transaction的factory類,從而在程式裡面可以直接使用Hibernate的事務API,也就是程式不用變化。另外一種方式就是直接通過JNDI去尋找UserTransaction,然後直接在程式裡面使用JTA的介面來控制事務。
應用程式層級的版本檢查 簡單點說,就是由應用程式自己實現版本檢查來確保對話事務的隔離,從資料訪問的角度來說是最低效的,不推薦使用。
擴充周期的session和自動版本化 Hibernate 使用擴充周期的 Session 的方式,或者脫管對象執行個體的方式來提供自動版本檢查。單個 Session 執行個體和它所關聯的所有持久化對象執行個體都被用於整個對話,這被稱為 sessionper-
conversation。 Hibernate 在同步的時候進行對象執行個體的版本檢查,如果檢測到並發修改則拋出異常。由開發人員來決定是否需要捕獲和處理這個異常(通常的抉擇是給使用者 提供一個合并更改,或者在無髒資料情況下重新進行業務對話的機會)。在等待使用者互動的時候, Session 斷開底層的 JDBC 串連。這種方式以資料庫訪問的角度來說是最高效的方式。應用程式不需要關心版本檢查或脫管對象執行個體的重新關聯,在每個資料庫事務中,應用程式也不需要載入讀取對象執行個體。
應用程式層級的版本檢查 簡單點說,就是由應用程式自己實現版本檢查來確保對話事務的隔離,從資料訪問的角度來說是最低效的,不推薦使用。
擴充周期的session和自動版本化 Hibernate 使用擴充周期的 Session 的方式,或者脫管對象執行個體的方式來提供自動版本檢查。單個 Session 執行個體和它所關聯的所有持久化對象執行個體都被用於整個對話,這被稱為 sessionper-conversation。Hibernate 在同步的時候進行對象執行個體的版本檢查,如果檢測到並發修改則拋出異常。由開發人員來決定是否需要捕獲和處理這個異常(通常的抉擇是給使用者 提供一個合并更改,或者在無髒資料情況下重新進行業務對話的機會)。在等待使用者互動的時候, Session 斷開底層的 JDBC 串連。這種方式以資料庫訪問的角度來說是最高效的方式。應用程式不需要關心版本檢查或脫管對象執行個體的重新關聯,在每個資料庫事務中,應用程式也不需要載入讀取對象執行個體。
通常不需要自己去管理鎖定策略 Hibernate 總是使用資料庫的鎖定機制,從不在記憶體中鎖定對象。因而使用者並不需要花很多精力去擔心鎖定策略的問題。通常情況下,只要為 JDBC 串連指定一下隔離等級,然後讓資料庫去搞定一切就夠了。然而,進階使用者有時候希望進行一個排它的悲觀鎖定,或者在一個新的事務啟動的時候,重新進行鎖定。
類 LockMode 定義了Hibernate 所需的不同的鎖定層級1:當更新或者插入一行記錄的時候,鎖定層級自動化佈建為LockMode.WRITE。 2:當使用者顯式的使用資料庫支援的 SQL 格式 SELECT ... FOR UPDATE 發送 SQL 的時候,鎖定層級設定為 LockMode.UPGRADE。3:當使用者顯式的使用 Oracle 資料庫的 SQL 陳述式 SELECT ... FOR UPDATE NOWAIT 的時候,鎖定層級設定 LockMode.UPGRADE_NOWAIT。4:當 Hibernate 在“可重複讀”或者是“序列化”資料庫隔離等級下讀取資料的時候,鎖定模式自動化佈建為 LockMode.READ。這種模式也可以通過使用者顯式指定進行設定。5:LockMode.NONE 代表無需鎖定。在 Transaction 結束時, 所有的對象都切換到該模式上來。與session 相關聯的對象通過調用 update() 或者 saveOrUpdate() 脫離該模式。
顯示的指定鎖定模式 1:調用 Session.load() 的時候指定鎖定模式(LockMode)。 2:調用 Session.lock()。 3:調用 Query.setLockMode()。
顯示指定鎖定模式的說明 1:如果在 UPGRADE 或者 UPGRADE_NOWAIT 鎖定模式下調用 Session.load(),並且要讀取的對象尚未被session 載入過,那麼對象通過 SELECT ... FOR UPDATE 這樣的 SQL 陳述式被載入。如果為一個對象調用 load() 方法時,該對象已經在另一個較少限制的鎖定模式下被載入了,那麼 Hibernate 就對該對象調用 lock() 方法。2:如果指定的鎖定模式是 READ,UPGRADE 或 UPGRADE_NOWAIT,那麼 Session.lock() 就執行版本號碼檢查。(在 UPGRADE 或者 UPGRADE_NOWAIT 鎖定模式下,執行 SELECT ... FOR UPDATE這樣的SQL語句。)3:如果資料庫不支援使用者佈建的鎖定模式,Hibernate 將使用適當的替代模式(而不是扔出異常)。這一點可以確保應用程式的可移植性。 原創內容 轉自請註明【
http://sishuok.com/forum/blogPost/list/2481.html#7178】 視頻配套PPT,視頻地址【 Hibernate4實戰-獨家視頻課程 】