欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java中JDBC事務與JTA分布式事務總結(jié)與區(qū)別

 更新時間:2016年11月01日 15:25:51   作者:boonya  
Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務,本文詳細介紹了JDBC事務與JTA分布式事務,有需要的可以了解一下。

Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務。常見的容器事務如Spring事務,容器事務主要是J2EE應用服務器提供的,容器事務大多是基于JTA完成,這是一個基于JNDI的,相當復雜的API實現(xiàn)。所以本文暫不討論容器事務。本文主要介紹J2EE開發(fā)中兩個比較基本的事務:JDBC事務和JTA事務。

JDBC事務

JDBC的一切行為包括事務是基于一個Connection的,在JDBC中是通過Connection對象進行事務管理。在JDBC中,常用的和事務相關(guān)的方法是: setAutoCommit、commit、rollback等。

下面看一個簡單的JDBC事務代碼:

public void JdbcTransfer() {  
  java.sql.Connection conn = null; 
   try{  
    conn = conn =DriverManager.getConnection("jdbc:oracle:thin:@host:1521:SID","username","userpwd"); 
     // 將自動提交設置為 false, 
     //若設置為 true 則數(shù)據(jù)庫將會把每一次數(shù)據(jù)更新認定為一個事務并自動提交 
     conn.setAutoCommit(false); 
 
     stmt = conn.createStatement();  
     // 將 A 賬戶中的金額減少 500  
     stmt.execute("\ 
     update t_account set amount = amount - 500 where account_id = 'A'"); 
     // 將 B 賬戶中的金額增加 500  
     stmt.execute("\ 
     update t_account set amount = amount + 500 where account_id = 'B'"); 
 
     // 提交事務 
     conn.commit(); 
     // 事務提交:轉(zhuǎn)賬的兩步操作同時成功 
   } catch(SQLException sqle){       
     try{  
       // 發(fā)生異常,回滾在本事務中的操做 
      conn.rollback(); 
       // 事務回滾:轉(zhuǎn)賬的兩步操作完全撤銷 
       stmt.close();  
       conn.close();  
     }catch(Exception ignore){  
 
     }  
     sqle.printStackTrace();  
   }  
} 

上面的代碼實現(xiàn)了一個簡單的轉(zhuǎn)賬功能,通過事務來控制轉(zhuǎn)賬操作,要么都提交,要么都回滾。

JDBC事務的優(yōu)缺點

JDBC為使用Java進行數(shù)據(jù)庫的事務操作提供了最基本的支持。通過JDBC事務,我們可以將多個SQL語句放到同一個事務中,保證其ACID特性。JDBC事務的主要優(yōu)點就是API比較簡單,可以實現(xiàn)最基本的事務操作,性能也相對較好。

但是,JDBC事務有一個局限:一個 JDBC 事務不能跨越多個數(shù)據(jù)庫?。?!所以,如果涉及到多數(shù)據(jù)庫的操作或者分布式場景,JDBC事務就無能為力了。

JTA事務

為什么需要JTA

通常,JDBC事務就可以解決數(shù)據(jù)的一致性等問題,鑒于他用法相對簡單,所以很多人關(guān)于Java中的事務只知道有JDBC事務,或者有人知道框架中的事務(比如Hibernate、Spring)等。但是,由于JDBC無法實現(xiàn)分布式事務,而如今的分布式場景越來越多,所以,JTA事務就應運而生。

如果,你在工作中沒有遇到JDBC事務無法解決的場景,那么只能說你做的項目還都太小。拿電商網(wǎng)站來說,我們一般把一個電商網(wǎng)站橫向拆分成商品模塊、訂單模塊、購物車模塊、消息模塊、支付模塊等。然后我們把不同的模塊部署到不同的機器上,各個模塊之間通過遠程服務調(diào)用(RPC)等方式進行通信。以一個分布式的系統(tǒng)對外提供服務。

一個支付流程就要和多個模塊進行交互,每個模塊都部署在不同的機器中,并且每個模塊操作的數(shù)據(jù)庫都不一致,這時候就無法使用JDBC來管理事務。我們看一段代碼:

/** 支付訂單處理 **/ 
@Transactional(rollbackFor = Exception.class) 
public void completeOrder() { 
  orderDao.update(); // 訂單服務本地更新訂單狀態(tài) 
  accountService.update(); // 調(diào)用資金賬戶服務給資金帳戶加款 
  pointService.update(); // 調(diào)用積分服務給積分帳戶增加積分 
  accountingService.insert(); // 調(diào)用會計服務向會計系統(tǒng)寫入會計原始憑證 
  merchantNotifyService.notify(); // 調(diào)用商戶通知服務向商戶發(fā)送支付結(jié)果通知 
} 

上面的代碼是一個簡單的支付流程的操作,其中調(diào)用了五個服務,這五個服務都通過RPC的方式調(diào)用,請問使用JDBC如何保證事務一致性?我在方法中增加了@Transactional注解,但是由于采用調(diào)用了分布式服務,該事務并不能達到ACID的效果。

JTA事務比JDBC事務更強大。一個JTA事務可以有多個參與者,而一個JDBC事務則被限定在一個單一的數(shù)據(jù)庫連接。下列任一個Java平臺的組件都可以參與到一個JTA事務中:JDBC連接、JDO PersistenceManager 對象、JMS 隊列、JMS 主題、企業(yè)JavaBeans(EJB)、一個用J2EE Connector Architecture 規(guī)范編譯的資源分配器。

JTA的定義

Java事務API(Java Transaction API,簡稱JTA ) 是一個Java企業(yè)版 的應用程序接口,在Java環(huán)境中,允許完成跨越多個XA資源的分布式事務。

JTA和它的同胞Java事務服務(JTS;Java TransactionService),為J2EE平臺提供了分布式事務服務。不過JTA只是提供了一個接口,并沒有提供具體的實現(xiàn),而是由j2ee服務器提供商 根據(jù)JTS規(guī)范提供的,常見的JTA實現(xiàn)有以下幾種:

1.J2EE容器所提供的JTA實現(xiàn)(JBoss)

2.獨立的JTA實現(xiàn):如JOTM,Atomikos.這些實現(xiàn)可以應用在那些不使用J2EE應用服務器的環(huán)境里用以提供分布事事務保證。如Tomcat,Jetty以及普通的java應用。

JTA里面提供了 java.transaction.UserTransaction ,里面定義了下面幾個方法

  •  begin:開啟一個事務
  • commit:提交當前事務
  • rollback:回滾當前事務
  • setRollbackOnly:把當前事務標記為回滾
  • setTransactionTimeout:設置事務的事件,超過這個事件,就拋出異常,回滾事務

這里,值得注意的是,不是使用了UserTransaction就能把普通的JDBC操作直接轉(zhuǎn)成JTA操作,JTA對DataSource、Connection和Resource 都是有要求的,只有符合XA規(guī)范,并且實現(xiàn)了XA規(guī)范的相關(guān)接口的類才能參與到JTA事務中來,關(guān)于XA規(guī)范,請看我的另外一篇文章中有相關(guān)介紹。這里,提一句,目前主流的數(shù)據(jù)庫都支持XA規(guī)范。

要想使用用 JTA 事務,那么就需要有一個實現(xiàn) javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅(qū)動程序。一個實現(xiàn)了這些接口的驅(qū)動程序?qū)⒖梢詤⑴c JTA 事務。一個 XADataSource 對象就是一個 XAConnection 對象的工廠。XAConnection 是參與 JTA 事務的 JDBC 連接。

要使用JTA事務,必須使用XADataSource來產(chǎn)生數(shù)據(jù)庫連接,產(chǎn)生的連接為一個XA連接。

XA連接(javax.sql.XAConnection)和非XA(java.sql.Connection)連接的區(qū)別在于:XA可以參與JTA的事務,而且不支持自動提交。

示例代碼:

public void JtaTransfer() {  
    javax.transaction.UserTransaction tx = null; 
    java.sql.Connection conn = null; 
     try{  
       tx = (javax.transaction.UserTransaction) context.lookup("java:comp/UserTransaction"); //取得JTA事務,本例中是由Jboss容器管理 
       javax.sql.DataSource ds = (javax.sql.DataSource) context.lookup("java:/XAOracleDS"); //取得數(shù)據(jù)庫連接池,必須有支持XA的數(shù)據(jù)庫、驅(qū)動程序  
       tx.begin(); 
      conn = ds.getConnection(); 
 
       // 將自動提交設置為 false, 
       //若設置為 true 則數(shù)據(jù)庫將會把每一次數(shù)據(jù)更新認定為一個事務并自動提交 
       conn.setAutoCommit(false); 
 
       stmt = conn.createStatement();  
       // 將 A 賬戶中的金額減少 500  
       stmt.execute("\ 
       update t_account set amount = amount - 500 where account_id = 'A'"); 
       // 將 B 賬戶中的金額增加 500  
       stmt.execute("\ 
       update t_account set amount = amount + 500 where account_id = 'B'"); 
 
       // 提交事務 
       tx.commit(); 
       // 事務提交:轉(zhuǎn)賬的兩步操作同時成功 
     } catch(SQLException sqle){       
       try{  
         // 發(fā)生異常,回滾在本事務中的操做 
       tx.rollback(); 
         // 事務回滾:轉(zhuǎn)賬的兩步操作完全撤銷 
         stmt.close();  
         conn.close();  
       }catch(Exception ignore){  
 
       }  
       sqle.printStackTrace();  
     }  
   } 

上面的例子就是一個使用JTA事務的轉(zhuǎn)賬操作,該操作相對依賴于J2EE容器,并且需要通過JNDI的方式獲取UserTransaction和Connection。

標準的分布式事務

一個分布式事務(Distributed Transaction)包括一個事務管理器(transaction manager)和一個或多個資源管理器(resource manager)。一個資源管理器(resource manager)是任意類型的持久化數(shù)據(jù)存儲。事務管理器(transaction manager)承擔著所有事務參與單元者的相互通訊的責任。

看上面關(guān)于分布式事務的介紹是不是和2PC中的事務管理比較像?的卻,2PC其實就是符合XA規(guī)范的事務管理器協(xié)調(diào)多個資源管理器的一種實現(xiàn)方式。 我之前有幾篇文章關(guān)于2PC和3PC的,那幾篇文章中介紹過分布式事務中的事務管理器是如何協(xié)調(diào)多個事務的統(tǒng)一提交或回滾的,后面我還會有幾篇文章詳細的介紹一下和分布式事務相關(guān)的內(nèi)容,包括但不限于全局事務、DTP模型、柔性事務等。

JTA的優(yōu)缺點

JTA的優(yōu)點很明顯,就是提供了分布式事務的解決方案,嚴格的ACID。但是,標準的JTA方式的事務管理在日常開發(fā)中并不常用,因為他有很多缺點:

實現(xiàn)復雜

通常情況下,JTA UserTransaction需要從JNDI獲取。這意味著,如果我們使用JTA,就需要同時使用JTA和JNDI。
JTA本身就是個笨重的API。
通常JTA只能在應用服務器環(huán)境下使用,因此使用JTA會限制代碼的復用性。

總結(jié)

Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務,其中JDBC的事務操作用法比較簡單,適合于處理同一個數(shù)據(jù)源的操作。JTA事務相對復雜,可以用于處理跨多個數(shù)據(jù)庫的事務,是分布式事務的一種解決方案。

這里還要簡單說一下,雖然JTA事務是Java提供的可用于分布式事務的一套API,但是不同的J2EE平臺的實現(xiàn)都不一樣,并且都不是很方便使用,所以,一般在項目中不太使用這種較為負責的API?,F(xiàn)在業(yè)內(nèi)比較常用的分布式事務解決方案主要有異步消息確保型、TCC、最大努力通知等。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • 簡單了解Java刪除字符replaceFirst原理及實例

    簡單了解Java刪除字符replaceFirst原理及實例

    這篇文章主要介紹了簡單了解Java刪除字符replaceFirst原理及實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-05-05
  • Springboot之如何統(tǒng)計代碼執(zhí)行耗時時間

    Springboot之如何統(tǒng)計代碼執(zhí)行耗時時間

    這篇文章主要介紹了Springboot之如何統(tǒng)計代碼執(zhí)行耗時時間問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-03-03
  • Java?事務注解@Transactional回滾(try?catch、嵌套)問題

    Java?事務注解@Transactional回滾(try?catch、嵌套)問題

    這篇文章主要介紹了Java?@Transactional回滾(try?catch、嵌套)問題,Spring?事務注解?@Transactional?本來可以保證原子性,如果事務內(nèi)有報錯的話,整個事務可以保證回滾,但是加上try?catch或者事務嵌套,可能會導致事務回滾失敗
    2022-08-08
  • Java基于redis和mysql實現(xiàn)簡單的秒殺(附demo)

    Java基于redis和mysql實現(xiàn)簡單的秒殺(附demo)

    這篇文章主要介紹了Java基于redis和mysql實現(xiàn)簡單的秒殺(附demo),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • 如何在IDEA中快速解決Jar沖突詳解

    如何在IDEA中快速解決Jar沖突詳解

    相信很多同學在過去做項目都遇到過Jar沖突的問題,在本地環(huán)境沒問題,一旦部署到測試或生產(chǎn)環(huán)境突然就啟動報錯,報類似classNotFound的Exception,本文詳細整理了如何在IDEA中快速解決Jar沖突,需要的朋友可以參考下
    2021-06-06
  • 基于SpringBoot項目遇到的坑--Date入?yún)栴}

    基于SpringBoot項目遇到的坑--Date入?yún)栴}

    這篇文章主要介紹了SpringBoot項目遇到的坑--Date入?yún)栴},具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-10-10
  • Java Scanner用法案例詳解

    Java Scanner用法案例詳解

    這篇文章主要介紹了Java Scanner用法案例詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • SpringBoot整合Redisson的步驟(單機版)

    SpringBoot整合Redisson的步驟(單機版)

    Redisson非常適用于分布式鎖,而我們的一項業(yè)務需要考慮分布式鎖這個應用場景,于是我整合它做一個初步簡單的例子(和整合redis一樣)。
    2021-05-05
  • Mybatis 中的sql批量修改方法實現(xiàn)

    Mybatis 中的sql批量修改方法實現(xiàn)

    在項目中遇到需要批量更新的功能,原本想的是在Java中用循環(huán)訪問數(shù)據(jù)庫去更新,但是心里總覺得這樣做會不會太頻繁了,太耗費資源了,效率也很低,查了下mybatis的批量操作,原來確實有<foreach>標簽可以做到,下面通過本文給大家介紹下
    2017-01-01
  • SpringBoot 監(jiān)控管理模塊actuator沒有權(quán)限的問題解決方法

    SpringBoot 監(jiān)控管理模塊actuator沒有權(quán)限的問題解決方法

    這篇文章主要介紹了SpringBoot 監(jiān)控管理模塊actuator沒有權(quán)限的問題解決方法,需要的朋友可以參考下
    2017-12-12

最新評論