文章轉自:Hibernate的事務管理
Hibernate的事務管理
事務(Transaction)是工作中的基本邏輯單位,可以用於確保數據庫能夠被正確修改,避免數據只修改了一部分而導致數據不完整,或者在修改時受到用戶干擾。作爲一名軟件設計師,必須瞭解事務併合理利用,以確保數據庫保存正確、完整的數據。數據庫向用戶提供保存當前程序狀態的方法,叫事務提交(commit);當事務執行過程中,使數據庫忽略當前的狀態並回到前面保存的狀態的方法叫事務回滾(rollback)。
1 事務的特性
事務具備原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)和持久性(Durability)4個屬性,簡稱ACID。下面對這4個特性分別進行說明。
原子性:將事務中所做的操作捆綁成一個原子單元,即對於事務所進行的數據修改等操作,要麼全部執行,要麼全部不執行。
一致性:事務在完成時,必須使所有的數據都保持一致狀態,而且在相關數據中,所有規則都必須應用於事務的修改,以保持所有數據的完整性。事務結束時,所有的內部數據結構都應該是正確的。
隔離性:由併發事務所做的修改必須與任何其他事務所做的修改相隔離。事務查看數據時數據所處的狀態,要麼是被另一併發事務修改之前的狀態,要麼是被另一併發事務修改之後的狀態,即事務不會查看由另一個併發事務正在修改的數據。這種隔離方式也叫可串行性。
持久性:事務完成之後,它對系統的影響是永久的,即使出現系統故障也是如此。
2 事務隔離
隔 離 級 別 | 髒讀(Dirty Read) | 不可重讀(Unrepeatable read) | 幻讀(Phantom Read) |
讀操作未提交(Read Uncommitted) | 可能 | 可能 | 可能 |
讀操作已提交(Read Committed) | 不可能 | 可能 | 可能 |
可重讀(Repeatable Read) | 不可能 | 不可能 | 可能 |
可串行化(Serializable) | 不可能 | 不可能 | 不可能 |
JDBC連接數據庫使用的是默認隔離級別,即讀操作已提交(Read Committed)和可重讀(Repeatable Read)。在hibernate的配置文件hibernate.properties中,可以修改隔離級別:
#hibernate.connection.isolation 4 |
在上一行代碼中,Hibernate事務的隔離級別是4,這是什麼意思呢?級別的數字意義如下。
1:讀操作未提交(Read Uncommitted) 2:讀操作已提交(Read Committed) 4:可重讀(Repeatable Read) 8:可串行化(Serializable)
因此,數字4表示“可重讀”隔離級別。如果要使以上語句有效,應把此語句行前的註釋符“#”去掉:
hibernate.connection.isolation 4 |
<session-factory> ….. //把隔離級別設置爲4 <property name=” hibernate.connection.isolation”>4</property> …… </session-factory> |
Hibernate對JDBC進行了輕量級的封裝,它本身在設計時並不具備事務處理功能。Hibernate將底層的JDBCTransaction或JTATransaction進行了封裝,再在外面套上Transaction和Session的外殼,其實是通過委託底層的JDBC或JTA來實現事務的處理功能的。
要在Hibernate中使用事務,可以在它的配置文件中指定使用JDBCTransaction或者JTATransaction。在hibernate.properties中,查找“transaction.factory_class”關鍵字,得到以下配置:
# hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory # hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory |
Hibernate的事務工廠類可以設置成JDBCTransactionFactory或者JTATransactionFactory。如果不進行配置,Hibernate就會認爲系統使用的事務是JDBC事務。
在JDBC的提交模式(commit mode)中,如果數據庫連接是自動提交模式(auto commit mode),那麼在每一條SQL語句執行後事務都將被提交,提交後如果還有任務,那麼一個新的事務又開始了。
Hibernate在Session控制下,在取得數據庫連接後,就立刻取消自動提交模式,即Hibernate在一個執行Session的beginTransaction()方法後,就自動調用JDBC層的setAutoCommit(false)。如果想自己提供數據庫連接並使用自己的SQL語句,爲了實現事務,那麼一開始就要把自動提交關掉(setAutoCommit(false)),並在事務結束時提交事務。
使用JDBC事務是進行事務管理最簡單的實現方式,Hibernate對於JDBC事務的封裝也很簡單。下面是一個在Hibernate中使用JDBC事務的例子:
try { Session session = HibernateUtil.currentSession(); Transaction tx = session.beginTransaction(); //在默認情況下,開啓一個JDBC事物 for(int i=0; i<10; i++) { Student stu = new Student(); stu.setName("Student" + i); session.save(stu); } tx.commit(); //提交事務 session.close(); } catch(Exception e) {… tx.rollback(); //事務回滾 } |
JTA(Java Transaction API)是事務服務的J2EE解決方案。本質上,它是描述事務接口的J2EE模型的一部分,開發人員直接使用該接口或者通過J2EE容器使用該接口來確保業務邏輯能夠可靠地運行。
JTA有3個接口,它們分別是UserTransaction接口、TransactionManager接口和Transaction接口。這些接口共享公共的事物操作,例如commit()和rollback(),但也包含特殊的事務操作,例如suspend()、resume()和enlist(),它們只出現在特定的接口上,以便在實現中允許一定程度的訪問控制。
在一個具有多個數據庫的系統中,可能一個程序會調用幾個數據庫中的數據,需要一種分佈式事務,或者準備用JTA來管理跨Session的長事務,那麼就需要使用JTA事務。下面介紹如何在Hibernate的配置文件中配置JTA事務。在hibernate.properties文件中設置如下(把JTATransactionFactory所在的配置行的註釋符“#”取消掉):
hibernate.transaction.factory_class org.hibernate.transaction.JTATransactionFactory # hibernate.transaction.factory_class org.hibernate.transaction.JDBCTransactionFactory |
<session-factory> ….. <property name=” hibernate.transaction.factory_class”> org.hibernate.transaction.JTATransactionFactory </property> …… </session-factory> |
javax.transaction.UserTransaction tx = null; tx = new initialContext().lookup(” javax.transaction.UserTransaction ”) ; tx.begin(); Session s1 = sf.openSession(); …… s1.flush(); s1.close(); Session s2 = sf.openSession(); …… s2.flush(); s2.close(); tx.commit(); |