1、事務
1-1、類別
● 本地事務
如果事務只和一個資源管理器有關,則為本地事物。在本地事務中,事務管理器只是將事務的管理委托給底層的資源管理器。
● 分布式事務
分布式事務和多個可能不同的資源管理器以一種協調的方式進行交互。
1-2、Java 中事務處理
JDBC 事務:由底層數據庫事務管理器控制,操作比較簡單,但是不適合控制多個應用程序組件的事務,并且沒有傳播的上下問。
JTA 和 JTS:Java 事務 API 和 Java 事務服務,可以跨越多個組件和數據庫使用事務。在應用程序使用 JTA 控制事務操作時,需要從 JNDI 上下文中獲取 UserTranscation 和數據源。
UserTranscation ut = (UserTranscation) ctx.lookup("UserTranscation");
1-3、Hibernate 事務
● 基于 JDBC
Transcation 事務對象必須從 Session 中獲取,即事務必須和一個 Session 相關聯。
采用 Hibernate 內置的 current session 和上下文管理。
<property name="current_session_context_class">thread</property>
...
sessionFactory.getCurrentSession().beginTranscation();
● 基于 JTA
提供了跨 Session 的事務管理能力。
使用 SessionFactory.getCurrentSession() 方法簡化事務上下文的傳播,即在事務綁定 Session。
雖然一個 Session 范圍內可以存在多個事務操作,但是 Hibernate 并不支持嵌套的事務模型。
tx1
tx2
...
tx2.commit();
//數據庫操作,操作無效
tx1.commit();
2、并發控制
如果事務都是串行執行,則許多資源將處于空閑狀態。為了充分利用資源,發揮數據庫共享資源的優勢,必須允許多個事務并發地執行。
在單處理機系統中,事務并發執行實際上是這些并行事務輪流交叉執行,即交叉并發方式,并不是真正的并行執行。在多處理機系統中,每個處理機運行一個事務,實現事務真正意義上的并存運行,即同時并發方式。
當多個用戶并發地存取數據庫時,就會產生多個事務同時存取同一數據的情況。所以,必須實現一個控制系統,使一個事務所做的修改不會對其他事務所做的修改產生負面影響,這就是并發控制。
2-1、封鎖
對并發操作進行的正確調度,防止并發操作破壞了事務的隔離性。采用封鎖技術,事務 T 可以向系統發出請求,對某個對象例如表、記錄加鎖,在事務 T 釋放鎖之前,其他事務不能更新這些數據對象。
基本的封鎖有:
排他鎖(Exclusive Locks,X 鎖):寫鎖或者獨占鎖。
共享鎖(Share Locks,S 鎖):讀鎖。允許和其他事務一起讀取數據對象D,但不能對D 做任何修改。
2-2、事務隔離
使用封鎖技術,事務對申請的資源加鎖,但是會影響數據庫性能。根據數據對象封鎖的程度,可以分成多種不同的事務隔離級別。
數據并發執行時,產生不一致的現象:
丟失更新(Lost Update)
兩個事務讀入同一數據并修改,然后提交修改,T2 提交的結果破壞了 T1 提交的結果,導致 T1 的修改丟失。
② 不可重復讀
事務T1 讀取數據后,事務T2 執行了同一數據的跟新操作,使得事務 T1 無法再現前一次讀取的結果。
事務1 讀取某一數據后,事務2 對該數據作了修改,事務1 再次讀取時,得到數據和前一次不一致。
① 事務1 讀取某一些記錄后,事務2 刪除了同一數據源的部分數據,事務1 再次讀取時,發現某些記錄丟失。
① 事務1 讀取某一些記錄后,事務2 插入了同一數據源的新數據,事務1 再次讀取時,發現某些記錄增加。
③ 讀“臟”數據
事務T1 修改某一數據,并將其寫回物理數據庫。事務T2 讀取同一數據后,事務T1 由于某種原因被撤銷,數據庫將已經修改的數據恢復原值,導致事務T2 保持的數據和數據庫中的數據產生了不一致。
ANSI SQL-99 標準定義了下列隔離級別:
● 未提交讀(Read Uncommitted):隔離事務的最低級別,只能保證不會讀取到物理上損壞的數據。H:1;允許產生:①②③
● 已提交讀(Read Committed):常見數據庫引擎的默認級別,保證一個事務不會讀取到另一個事務已修改但未提交的數據。H:2;允許產生:①②
● 可重復讀(Repeatable Read):保證一個事務不能更新已經由另一個事務讀取但是未提交的數據。相當于應用中的已提交讀和樂觀并發控制。H:4;允許產生:①
● 可串行化(Serializable):隔離事務的最高級別,事務之間完全隔離。系統開銷最大。H:8;允許產生:
在數據庫中,可以手工設置事務的隔離級別。
Hibernate 在配置文件中聲明事務的隔離級別,Hibenate 獲取數據庫連接后,將根據隔離級別自動設置數據庫連接為指定的事務隔離級別。
<property name="connection.isolation">8</property>
2-3、并發控制類型
根據使用的鎖定策略和隔離等級,可以把事務的并發控制分為兩種:
① 悲觀并發控制
用戶使用時鎖定數據。主要應用于數據爭用激烈的環境中,以及發生并發沖突時用鎖保護數據的成本低于回滾事務成本的環境中。
Hibernate 的悲觀鎖定不在內存中鎖定數據,由底層數據庫負責完成。
② 樂觀并發控制
用戶讀取數據時不鎖定數據。當一個用戶更新數據時,系統將進行檢查該用戶讀取數據后其他用戶是否更改了該數據,是則產生一個錯誤,一般情況下,收到錯誤信息的用戶將回滾事務并重新開始。主要用戶數據爭用不大,且偶爾回滾事務的成本低于讀取數據時鎖定數據的成本的環境中。
Hibernate 中使用元素 version 和 timestamp 實現樂觀并發控制模式的版本控制,并提供多種編程方式。版本是數據庫表中的一個字段,可以是一個遞增的整數,也可以是一個時間戳,它們對應 Java 持久化類的一個屬性。事務提交成功后,Hibernate 自動修改版本號。如果另外一個事務同時訪問同一數據,若發現提交前的版本號和事前載入的版本號有出入,則認為發生了沖突,事務停止執行,撤銷操作,并拋出異常。應用程序必須捕捉該異常并做出一定的處理。
⒈應用程序級別的版本控制
⒉長生命周期會話的自動化版本控制
⒊托管對象的自動化版本控制
⒋定制自動化版本控制
3、Hibernate 緩存
Hibernate 提供兩級緩存架構,第一級緩存是 Session 內的緩存,第二級緩存是一個可插拔的緩存,能夠借助第三方的組件實現。如果應用程序中經常使用同樣的條件查詢數據,還可以使用查詢緩存來提高查詢效率。
針對緩存的范圍,可以將 Hibernate 持久層緩存分為三個層次:
① 事務級緩存
緩存只能被當前事務訪問。緩存的生命周期以來與事務的生命周期。事務緩存由 Session 實現。一個 Session 的緩存的內容只有在本 Session 實例范圍內可用。
② 應用級緩存
緩存在某個應用范圍內被所有事務共享。緩存的生命周期依賴于應用程序的生命周期。應用級緩存由 SessionFactory 實現,Session 實例由其創建,并共享其緩存。
③ 分布式緩存
集群環境中,緩存被一個 JVM 或多個 JVM 的進程共享。分布式緩存由多個應用級的緩存實例組成,緩存中的數據被復制到集群環境中的每個 JVM 節點,JVM 間通過遠程通信來保證緩存中數據的一致性。
3-1、緩存查詢結果
經常使用同樣的條件查詢數據,則可使用查詢緩存。查詢緩存需要和二級緩存聯合使用,在二級緩存中,可以專門為查詢緩存開辟一個命名緩存區域。查詢緩存啟動后將創建兩個緩存區域,org.hibernate.cache.StandardQueryCache 實現保存查詢結果集;org.hibernate.cache.UpdateTimestampsCache 實現保存最近更新的查詢表的時間戳。
<property name="cache.use_query_cache">true</propery>
//使用查詢緩存
query.setCacheable(true);
//給查詢緩存指定特定的命名緩存區域
query.setCacheRegion("queryCache");
//如果其他進程更新了結果集,強行刷新緩沖區域
query.setCacheMode(CacheMode.REFRESH);
//刷新某個或全部的緩存
SessionFactory.evictQueries() 方法
4、高級特性
4-1、數據庫連接池 ConnectionProvider
J2SE 環境中使用建議。
4-2、使用數據源
Hibernate 中,DatasourceConnectionProvider 實現了 ConnectionProvider 接口并封裝了數據源的獲取方法,充當了 Hibernate 和數據源間的適配器。
J2EE 環境中使用建議。
4-3、過濾數據
把公共的數據過濾條件提取出來。從 Hibernate 3.0 開始,可以利用 Hibernate Filter 對某個類或集合附加預先定義的過濾條件,在查詢時過濾指定條件的數據。該過濾器是全局有效的,使用時候,還可以指定特定參數。
4-4、批量處理
批量處理引發異常的根源在于緩存中保存了過多的持久化實例而耗盡內存。
① 應用程序級別的批處理
指定 Hibernate 處理 SQL 語句時,必須積累到指定數量后再向數據庫提交操作。
<property name="jdbc.batch_size">20</property>
② 無狀態 Session(StatelessSession)
StatelessSession 接口沒有持久化上下文,也不負責持久化實例的生命周期,沒有一級緩存,操作也不會影響到二級和查詢緩存。
③ 使用 DML 風格的 HQL 語句繞過內存直接進行數據處理
"delete Product p where p.id > :id"
4-4、延遲加載
設置延遲加載的屬性和集合只能在該實例依附的 Session 范圍內被訪問,會話關閉后,實例從持久態轉為托管態,再次訪問該實例的一些屬性時候,有可能會拋出 LazyInitializationException 異常。
① 屬性延遲加載(大對象)
② 持久化類延遲加載
③ 集合延遲加載
4-5、數據抓取策略(Fetching strategies)
可以在 Hibernate 中設定相應的數據抓取策略,減少系統產生的數據庫查詢操作,優化系統性能。
在 Hibernate 中,延遲(lazy)定義了一種契約,用來表示托管狀態實例中那些數據是有效的,而抓取(fetch)是用來調整 Hibernate 性能的。
4-5、監控性能
org.hibernate.stat 包提供的工具類。
5、附錄
5-1、XML 元數據
18.2. XML映射元數據 - Hibernate reference 3.2.0 ga 正式版中文參考手冊
18.3. 操作XML數據 (通過dom4j會話讀入和更新應用程序中的XML文檔)
5-2、開源工具箱
CownewStudio 是一個基于 Eclipse 的 Hibernate 正向建模輔助工具。通過它用戶能以圖形化的方式建立對象模型,然后根據模型生成持久化類、映射文件和數據庫表。
JDBMonitor。模擬一個 JDBC 驅動來代替真正的 JDBC 驅動,截取應用程序對數據庫的操作,并以合適的方式記錄下來,提供性能分析的來源和依據。
posted on 2009-04-14 09:56
黃小二 閱讀(739)
評論(0) 編輯 收藏 所屬分類:
S/S2SH 、
J2EE 、
J2SE