JDBC事務(wù)

轉(zhuǎn)賬自:http://www.hollischuang.com/archives/1658


Java中的事務(wù)——JDBC事務(wù)和JTA事務(wù)

2016-08-14?分類:分布式?閱讀(11870)?評論(9)?

本站采用[知識共享署名-非商業(yè)性使用-相同方式共享 許可協(xié)議]進行許可严就,轉(zhuǎn)載請在正文明顯處注明原文地址

我的博客中曾經(jīng)關(guān)于事務(wù)有過很多討論补胚,之前的事務(wù)介紹基本都是數(shù)據(jù)庫層面的事務(wù)扰才,本文來介紹一下J2EE中和事務(wù)相關(guān)的內(nèi)容蠕嫁,在閱讀本文之前聪廉,希望讀者對分布式有一定的了解往枣。

關(guān)于事務(wù)的基礎(chǔ)知識這里不再詳細介紹送漠,想要了解的同學(xué)可以在我的博客中閱讀相關(guān)文章喧兄。

Java事務(wù)的類型有三種:JDBC事務(wù)、JTA(Java Transaction API)事務(wù)宅粥、容器事務(wù)参袱。 常見的容器事務(wù)如Spring事務(wù),容器事務(wù)主要是J2EE應(yīng)用服務(wù)器提供的秽梅,容器事務(wù)大多是基于JTA完成抹蚀,這是一個基于JNDI的,相當復(fù)雜的API實現(xiàn)风纠。所以本文暫不討論容器事務(wù)况鸣。本文主要介紹J2EE開發(fā)中兩個比較基本的事務(wù):JDBC事務(wù)和JTA事務(wù)牢贸。

JDBC事務(wù)

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

下面看一個簡單的JDBC事務(wù)代碼:

public void JdbcTransfer() {

? ? java.sql.Connection conn = null;? ? try{

? ? ? ? conn = conn =DriverManager.getConnection("jdbc:oracle:thin:@host:1521:SID","username","userpwd");? ? ? ? // 將自動提交設(shè)置為 false誊抛,? ? ? ? //若設(shè)置為 true 則數(shù)據(jù)庫將會把每一次數(shù)據(jù)更新認定為一個事務(wù)并自動提交? ? ? ? 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'");? ? ? ? // 提交事務(wù)? ? ? ? conn.commit();? ? ? ? // 事務(wù)提交:轉(zhuǎn)賬的兩步操作同時成功? ? } catch(SQLException sqle){? ? ? ? ? ?

? ? ? ? try{

? ? ? ? ? ? // 發(fā)生異常,回滾在本事務(wù)中的操做? ? ? ? ? ? conn.rollback();? ? ? ? ? ? // 事務(wù)回滾:轉(zhuǎn)賬的兩步操作完全撤銷? ? ? ? ? ? stmt.close();

? ? ? ? ? ? conn.close();

? ? ? ? }catch(Exception ignore){

? ? ? ? }

? ? ? ? sqle.printStackTrace();

? ? } }

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

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

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

但是乙各,JDBC事務(wù)有一個局限:一個 JDBC 事務(wù)不能跨越多個數(shù)據(jù)庫!4敝瘛耳峦!所以,如果涉及到多數(shù)據(jù)庫的操作或者分布式場景焕毫,JDBC事務(wù)就無能為力了妇萄。

JTA事務(wù)

為什么需要JTA

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

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

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

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

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

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

JTA的定義

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

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

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

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

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

begin:開啟一個事務(wù)

commit:提交當前事務(wù)

rollback:回滾當前事務(wù)

setRollbackOnly:把當前事務(wù)標記為回滾

setTransactionTimeout:設(shè)置事務(wù)的事件界睁,超過這個事件觉增,就拋出異常,回滾事務(wù)

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

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

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

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

public void JtaTransfer() {

? ? ? ? javax.transaction.UserTransaction tx = null;? ? ? ? java.sql.Connection conn = null;? ? ? ? try{

? ? ? ? ? ? tx = (javax.transaction.UserTransaction) context.lookup("java:comp/UserTransaction");? //取得JTA事務(wù),本例中是由Jboss容器管理? ? ? ? ? ? javax.sql.DataSource ds = (javax.sql.DataSource) context.lookup("java:/XAOracleDS");? //取得數(shù)據(jù)庫連接池州邢,必須有支持XA的數(shù)據(jù)庫婶溯、驅(qū)動程序? ? ? ? ? ? ? tx.begin();? ? ? ? ? ? conn = ds.getConnection();? ? ? ? ? ? // 將自動提交設(shè)置為 false,? ? ? ? ? ? //若設(shè)置為 true 則數(shù)據(jù)庫將會把每一次數(shù)據(jù)更新認定為一個事務(wù)并自動提交? ? ? ? ? ? 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'");? ? ? ? ? ? // 提交事務(wù)? ? ? ? ? ? tx.commit();? ? ? ? ? ? // 事務(wù)提交:轉(zhuǎn)賬的兩步操作同時成功? ? ? ? } catch(SQLException sqle){? ? ? ? ? ?

? ? ? ? ? ? try{

? ? ? ? ? ? ? ? // 發(fā)生異常偷霉,回滾在本事務(wù)中的操做? ? ? ? ? ? ? tx.rollback();? ? ? ? ? ? ? ? // 事務(wù)回滾:轉(zhuǎn)賬的兩步操作完全撤銷? ? ? ? ? ? ? ? stmt.close();

? ? ? ? ? ? ? ? conn.close();

? ? ? ? ? ? }catch(Exception ignore){

? ? ? ? ? ? }

? ? ? ? ? ? sqle.printStackTrace();

? ? ? ? }

? ? }

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

標準的分布式事務(wù)

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

JTA的實現(xiàn)方式也是基于以上這些分布式事務(wù)參與者實現(xiàn)的信轿,具體的關(guān)于JTA的實現(xiàn)細節(jié)不是本文的重點,感興趣的同學(xué)可以閱讀JTA 深度歷險 – 原理與實現(xiàn)

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

JTA的優(yōu)缺點

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

實現(xiàn)復(fù)雜

通常情況下轻庆,JTA UserTransaction需要從JNDI獲取。這意味著敛劝,如果我們使用JTA余爆,就需要同時使用JTA和JNDI。

JTA本身就是個笨重的API

通常JTA只能在應(yīng)用服務(wù)器環(huán)境下使用攘蔽,因此使用JTA會限制代碼的復(fù)用性龙屉。

總結(jié)

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

這里還要簡單說一下枢步,雖然JTA事務(wù)是Java提供的可用于分布式事務(wù)的一套API,但是不同的J2EE平臺的實現(xiàn)都不一樣渐尿,并且都不是很方便使用醉途,所以,一般在項目中不太使用這種較為負責(zé)的API∽┤祝現(xiàn)在業(yè)內(nèi)比較常用的分布式事務(wù)解決方案主要有異步消息確保型隘擎、TCC、最大努力通知等凉夯。關(guān)于這幾種分布式事務(wù)解決方案货葬,我會在后面的文章中介紹。歡迎關(guān)注與交流劲够。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末震桶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子征绎,更是在濱河造成了極大的恐慌蹲姐,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,743評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異淤堵,居然都是意外死亡寝衫,警方通過查閱死者的電腦和手機顷扩,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評論 3 385
  • 文/潘曉璐 我一進店門拐邪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人隘截,你說我怎么就攤上這事扎阶。” “怎么了婶芭?”我有些...
    開封第一講書人閱讀 157,285評論 0 348
  • 文/不壞的土叔 我叫張陵东臀,是天一觀的道長。 經(jīng)常有香客問我犀农,道長惰赋,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,485評論 1 283
  • 正文 為了忘掉前任呵哨,我火速辦了婚禮赁濒,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘孟害。我一直安慰自己拒炎,他們只是感情好,可當我...
    茶點故事閱讀 65,581評論 6 386
  • 文/花漫 我一把揭開白布挨务。 她就那樣靜靜地躺著击你,像睡著了一般。 火紅的嫁衣襯著肌膚如雪谎柄。 梳的紋絲不亂的頭發(fā)上丁侄,一...
    開封第一講書人閱讀 49,821評論 1 290
  • 那天,我揣著相機與錄音朝巫,去河邊找鬼鸿摇。 笑死,一個胖子當著我的面吹牛捍歪,可吹牛的內(nèi)容都是我干的户辱。 我是一名探鬼主播,決...
    沈念sama閱讀 38,960評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼糙臼,長吁一口氣:“原來是場噩夢啊……” “哼庐镐!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起变逃,我...
    開封第一講書人閱讀 37,719評論 0 266
  • 序言:老撾萬榮一對情侶失蹤必逆,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體名眉,經(jīng)...
    沈念sama閱讀 44,186評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡粟矿,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,516評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了损拢。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片陌粹。...
    茶點故事閱讀 38,650評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖福压,靈堂內(nèi)的尸體忽然破棺而出掏秩,到底是詐尸還是另有隱情,我是刑警寧澤荆姆,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布蒙幻,位于F島的核電站,受9級特大地震影響胆筒,放射性物質(zhì)發(fā)生泄漏邮破。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,936評論 3 313
  • 文/蒙蒙 一仆救、第九天 我趴在偏房一處隱蔽的房頂上張望抒和。 院中可真熱鬧,春花似錦派桩、人聲如沸构诚。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,757評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽范嘱。三九已至,卻和暖如春员魏,著一層夾襖步出監(jiān)牢的瞬間丑蛤,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,991評論 1 266
  • 我被黑心中介騙來泰國打工撕阎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留受裹,地道東北人。 一個月前我還...
    沈念sama閱讀 46,370評論 2 360
  • 正文 我出身青樓虏束,卻偏偏與公主長得像棉饶,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子镇匀,可洞房花燭夜當晚...
    茶點故事閱讀 43,527評論 2 349

推薦閱讀更多精彩內(nèi)容

  • Java事務(wù)的類型有三種:JDBC事務(wù)照藻、JTA(Java Transaction API)事務(wù)、容器事務(wù)汗侵。 常見的...
    余平的余_余平的平閱讀 1,456評論 0 10
  • 1幸缕、java事務(wù)介紹 2群发、JDBC事務(wù) 3、JTA事務(wù) 1发乔、java事務(wù)介紹 java事務(wù)分類:JDBC事務(wù)熟妓、...
    小樣兒的茅草屋閱讀 1,081評論 0 0
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語法,類相關(guān)的語法栏尚,內(nèi)部類的語法起愈,繼承相關(guān)的語法,異常的語法抵栈,線程的語...
    子非魚_t_閱讀 31,598評論 18 399
  • “錢可以救命告材,但理想不行坤次」啪ⅲ” 嚴格來說,這部電影才算大鵬的二號作品缰猴。影片票房并沒有大放異彩产艾,遠遠被同期的《羞羞的鐵...
    祭塵年閱讀 395評論 0 0
  • 那年杭州大雪。我在留下等你滑绒。 我說下雪天應(yīng)該吃頓熱燙的火鍋闷堡。 雪下的很大。我們等了很久疑故。店里滿滿的人我們被擠的靠邊...
    毛欣與小李閱讀 199評論 0 0