事務的定義
事務就是指作爲單個邏輯工作單元執行的一組數據操作,這些操作要麼必須全部成功,要麼必須全部失敗,以保證數據的一致性和完整性。
事務具有ACID屬性
原子性(Atomic):事務由一個或多個行爲綁在一起組成,好像是一個單獨的工作單元。原子性確保在事務中的所有操作要麼都發生,要麼都不發生。
一致性(Consistent):一旦一個事務結束了(不管成功與否),系統所處的狀態和它的業務規則是一致的。即數據應當不會被破壞。
隔離性(Isolated):事務應該允許多個用戶操作同一個數據,一個用戶的操作不會和其他用戶的操作相混淆。
持久性(Durable):一旦事務完成,事務的結果應該持久化。
事務的ACID特性是由關係數據庫管理系統(RDBMS)來實現的。
1)數據庫管理系統採用日誌來保證事務的原子性、一致性和持久性。日誌記錄了事務對數據庫所做的更新,如果某個事務在執行過程中發生錯誤,就可以根據日誌,撤銷事務對數據庫已做的更新,使數據庫退回到執行事務前的初始狀態。
2)數據庫管理系統採用鎖機制來實現事務的隔離性。當多個事務同時更新數據庫相同的數據時,只允許持有鎖的事務能更新該數據,其他事務必須等待,直到前一個事務釋放了鎖,其他事務纔有機會更新該數據。
數據庫事務聲明
數據庫系統的客戶程序只要向數據庫系統聲明瞭一個事務,數據庫系統就會自動保證事務的ACID特性。在JDBC API中,java.sql.Connection類代表一個數據庫連接。它提供了以下方法控制事務:
1. setAutoCommit(Boolean autoCommit):設置是否自動提交事務。
2. commit():提交事務。
3. rollback():撤銷事務
JDBC API聲明事務的示例代碼如下:
- <span style="font-size: large;">Connection = null;
- PreparedStatement pstmt = null;
- try{
- con = DriverManager.getConnection(dbUrl, username, password);
- //設置手工提交事務模式
- con.setAutoCommit(false);
- pstmt = ……;
- pstmt.executeUpdate();
- //提交事務
- con.commit();
- }catch(Exception e){
- //事務回滾
- con.rollback();
- …..
- } finally{
- …….
- }</span>
Hibernate 是JDBC 的輕量級封裝,本身並不具備事務管理能力。
在事務管理層, Hibernate將其委託給底層的JDBC或者JTA,只是將底層的JDBCTransaction或者JTATransaction進行封裝一下,在外邊套上Transaction和Session的外殼,以實現事務管理和調度功能。
1)Hibernate中使用JDBC事務
如果在Hibernate中使用JDBC事務,可以在hibernate.cfg.xml中指定Hibernate事務爲JDBCTransaction。如果不進行配置,Hibernate會默認使用JDBC事務。代碼如下
- <span style="font-size: large;"><span style="font-size: large;"><?xml version="1.0" encoding="utf-8" ?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="hibernate.transaction.factory_class">
- org.hibernate.transaction.JDBCTransactionFactory
- </property>
- </session-factory>
- </hibernate-configuration></span></span>
基於JDBC的事務管理將事務管理委託給JDBC 進行處理無疑是最簡單的實現方式,Hibernate 對於JDBC事務的封裝也極爲簡單。
我們來看下面這段代碼:
- <span style="font-size: large;"><span style="font-size: large;">Transaction tx=null;
- try{
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction(); //開啓事務
- //執行持久化操作
- ……
- tx.commit(); //操作正常,提交事務
- }catch(RuntimeException e){
- if(tx!=null){
- tx.rollback();//操作過程中有一場,回滾事務
- throw e;//處理異常
- }
- }finally{
- session.close()
- } </span></span>
- <span style="font-size: large;"><span style="font-size: large;">Connection dbconn = getConnection();
- dbconn.setAutoCommit(false);
- ……
- dbconn.commit(); </span></span>
這也就是說,我們一開始從SessionFactory獲得的session,其自動提交屬性就已經被關閉(AutoCommit=false),下面的代碼將不會對數據庫產生任何效果:
- <span style="font-size: large;"><span style="font-size: large;">session = sessionFactory.openSession();
- session.save(user);
- session.close();
- session = sessionFactory.openSession();
- session.save(user);
- session.close(); </span></span>
- <span style="font-size: large;"><span style="font-size: large;">session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(user);
- tx.commit();
- session.close(); </span></span>
- <span style="font-size: large;"><span style="font-size: large;"><?xml version="1.0" encoding="utf-8" ?>
- <!DOCTYPE hibernate-configuration PUBLIC
- "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
- "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
- <hibernate-configuration>
- <session-factory>
- <property name="hibernate.transaction.factory_class">
- org.hibernate.transaction.JTATransactionFactory
- </property>
- </session-factory>
- </hibernate-configuration></span></span>
- <span style="font-size: large;"><span style="font-size: large;">public class ClassA{
- public void saveUser(User user){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(user);
- tx.commit();
- session.close();
- }
- }
- public class ClassB{
- public void saveOrder(Order order){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(order);
- tx.commit();
- session.close();
- }
- }
- public class ClassC{
- public void save(){
- ……
- UserTransaction tx = new InitialContext().lookup(“……”);
- ClassA.save(user);
- ClassB.save(order);
- tx.commit();
- ……
- }
- }
- public class ClassA{
- public void saveUser(User user){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(user);
- tx.commit();
- session.close();
- }
- }
- public class ClassB{
- public void saveOrder(Order order){
- session = sessionFactory.openSession();
- Transaction tx = session.beginTransaction();
- session.save(order);
- tx.commit();
- session.close();
- }
- }
- public class ClassC{
- public void save(){
- try{
- UserTransaction tx = (UserTransaction)new InitialContext().lookup(“java:comp/UserTransaction”);
- tx.begin();//開啓JTA事務
- ClassA.save(user);
- ClassB.save(order);
- tx.commit();//操作正常,提交JTA事務
- }catch(RuntimeException e){
- tx.rollback();//操作異常,回滾JTA事務
- throw e;//異常處理
- }finally{
- }
- }
- }</span></span>
- <span style="font-size: large;"><span style="white-space: normal; font-size: 12px;"><span style="font-size: large;"><span style="font-size: large;"> </span></span><span style="white-space: pre;"><span style="font-size: large;"><span style="font-size: large;">public class ClassA{</span></span></span></span></span>
- <span style="font-size: large;"><span style="font-size: large;">public void save(TUser user){
- session = sessionFactory.openSession();
- session.save(user);
- session.close();
- }
- ……
- }
- public class ClassB{
- public void save (Order order){
- session = sessionFactory.openSession();
- session.save(order);
- session.close();
- }
- ……
- }
- public class ClassC{
- public void save(){
- ……
- UserTransaction tx = new InitialContext().lookup(“……”);
- classA.save(user);
- classB.save(order);
- tx.commit();
- ……
- }
- }
- public class ClassA{
- public void save(TUser user){
- session = sessionFactory.openSession();
- session.save(user);
- session.close();
- }
- ……
- }
- public class ClassB{
- public void save (Order order){
- session = sessionFactory.openSession();
- session.save(order);
- session.close();
- }
- ……
- }
- public class ClassC{
- public void save(){
- ……
- UserTransaction tx = new InitialContext().lookup(“……”);
- classA.save(user);
- classB.save(order);
- tx.commit();
- ……
- }
- }
- </span></span>
- <span style="font-size: large;"><span style="font-size: large;">/**
- * @ejb.interface-method
- * view-type="remote"
- *
- * @ejb.transaction type = "Required"
- **/
- public void save(){
- //EJB環境中,通過部署配置即可實現事務申明,而無需顯式調用事務
- classA.save(user);
- classB.save(log);
- }//方法結束時,如果沒有異常發生,則事務由EJB容器自動提交。</span></span>