java 事务_Java中事务总结详解(精华)
1.什么是JAVA事務(wù)?
通常的觀念認(rèn)為,事務(wù)僅與數(shù)據(jù)庫(kù)相關(guān)。
事務(wù)必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性 (isolation)和持久性(durability)的縮寫(xiě)。
事務(wù)的原子性:表示事務(wù)執(zhí)行過(guò)程中的任何失敗都將導(dǎo)致事務(wù)所做的任何修改失效。
事務(wù)的一致性:表示當(dāng)事務(wù)執(zhí)行失敗時(shí),所有被該事務(wù)影響的數(shù)據(jù)都應(yīng)該恢復(fù)到事務(wù)執(zhí)行前的狀態(tài)。
事務(wù)的隔離性:表示在事務(wù)執(zhí)行過(guò)程中對(duì)數(shù)據(jù)的修改,在事務(wù)提交之前對(duì)其他事務(wù)不可見(jiàn)。
事務(wù)的持久性:表示已提交的數(shù)據(jù)在事務(wù)執(zhí)行失敗時(shí),數(shù)據(jù)的狀態(tài)都應(yīng)該正確。
通俗的理解,事務(wù)是一組原子操作單元,從數(shù)據(jù)庫(kù)角度說(shuō),就是一組SQL指令,要么全部執(zhí)行成功,若因?yàn)槟硞€(gè)原因其中一條指令執(zhí)行有錯(cuò)誤,則撤銷(xiāo)先前執(zhí)行過(guò)的所有指令。更簡(jiǎn)答的說(shuō)就是:要么全部執(zhí)行成功,要么撤銷(xiāo)不執(zhí)行。
既然事務(wù)的概念從數(shù)據(jù)庫(kù)而來(lái),那Java事務(wù)是什么?之間有什么聯(lián)系?
實(shí)際上,一個(gè)Java應(yīng)用系統(tǒng),如果要操作數(shù)據(jù)庫(kù),則通過(guò)JDBC來(lái)實(shí)現(xiàn)的。增加、修改、刪除都是通過(guò)相應(yīng)方法間接來(lái)實(shí)現(xiàn)的,事務(wù)的控制也相應(yīng)轉(zhuǎn)移到Java程序代碼中。
因此,數(shù)據(jù)庫(kù)操作的事務(wù)習(xí)慣上就稱(chēng)為Java事務(wù)。
2. 為什么需要Java事務(wù)?
事務(wù)是為解決數(shù)據(jù)安全操作提出的,事務(wù)控制實(shí)際上就是控制數(shù)據(jù)的安全訪(fǎng)問(wèn)。
舉一個(gè)簡(jiǎn)單例子:
比如銀行轉(zhuǎn)帳業(yè)務(wù),賬戶(hù)A要將自己賬戶(hù)上的1000元轉(zhuǎn)到B賬 戶(hù)下面,A賬戶(hù)余額首先要減去1000元,然后B賬戶(hù)要增加1000元。假如在中間網(wǎng)絡(luò)出現(xiàn)了問(wèn)題,A賬戶(hù)減去1000元已經(jīng)結(jié)束,
B因?yàn)榫W(wǎng)絡(luò)中斷而操作 失敗,那么整個(gè)業(yè)務(wù)失敗,必須做出控制,要求A賬戶(hù)轉(zhuǎn)帳業(yè)務(wù)撤銷(xiāo)。這才能保證業(yè)務(wù)的正確性,完成這個(gè)操作就需要事務(wù),將A賬戶(hù)資金減少和B賬戶(hù)資金增加方
到一個(gè)事務(wù)里面,要么全部執(zhí)行成功,要么操作全部撤銷(xiāo),這樣就保持了數(shù)據(jù)的安全性。
3.Java事務(wù)的類(lèi)型
Java事務(wù)的類(lèi)型有三種:JDBC事務(wù)、JTA(Java Transaction API)事務(wù)、容器事務(wù)。
1.JDBC事務(wù)
JDBC 事務(wù)是用 Connection 對(duì)象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務(wù)模式:自動(dòng)提交和手工提交。
1 java.sql.Connection 提供了以下控制事務(wù)的方法:2
3 public void setAutoCommit(boolean)4 public booleangetAutoCommit()5 public voidcommit()6 public void rollback()
使用 JDBC 事務(wù)界定時(shí),您可以將多個(gè) SQL 語(yǔ)句結(jié)合到一個(gè)事務(wù)中。
JDBC 事務(wù)的一個(gè)缺點(diǎn)是事務(wù)的范圍局限于一個(gè)數(shù)據(jù)庫(kù)連接。一個(gè) JDBC 事務(wù)不能跨越多個(gè)數(shù)據(jù)庫(kù)。
2.JTA(Java Transaction API)事務(wù)
JTA是一種高層的,與實(shí)現(xiàn)無(wú)關(guān)的,與協(xié)議無(wú)關(guān)的API,應(yīng)用程序和應(yīng)用服務(wù)器可以使用JTA來(lái)訪(fǎng)問(wèn)事務(wù)。
JTA允許應(yīng)用程序執(zhí)行分布式事務(wù)處理——在兩個(gè)或多個(gè)網(wǎng)絡(luò)計(jì)算機(jī)資源上訪(fǎng)問(wèn)并且更新數(shù)據(jù),這些數(shù)據(jù)可以分布在多個(gè)數(shù)據(jù)庫(kù)上。JDBC驅(qū)動(dòng)程序的JTA支持極大地增強(qiáng)了數(shù)據(jù)訪(fǎng)問(wèn)能力。
如果計(jì)劃用 JTA 界定事務(wù),那么就需要有一個(gè)實(shí)現(xiàn) javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource 接口的 JDBC 驅(qū)動(dòng)程序。一個(gè)實(shí)現(xiàn)了這些接口的驅(qū)動(dòng)程序?qū)⒖梢詤⑴c JTA 事務(wù)。一個(gè) XADataSource 對(duì)象就是一個(gè) XAConnection 對(duì)象的工廠。 XAConnection s 是參與 JTA 事務(wù)的 JDBC 連接。
您將需要用應(yīng)用服務(wù)器的管理工具設(shè)置 XADataSource .從應(yīng)用服務(wù)器和 JDBC 驅(qū)動(dòng)程序的文檔中可以了解到相關(guān)的指導(dǎo)。
J2EE應(yīng)用程序用 JNDI 查詢(xún)數(shù)據(jù)源。一旦應(yīng)用程序找到了數(shù)據(jù)源對(duì)象,它就調(diào)用 javax.sql.DataSource.getConnection() 以獲得到數(shù)據(jù)庫(kù)的連接。
XA 連接與非 XA 連接不同。一定要記住 XA 連接參與了 JTA 事務(wù)。這意味著 XA 連接不支持 JDBC
的自動(dòng)提交功能。同時(shí),應(yīng)用程序一定不要對(duì) XA 連接調(diào)用 java.sql.Connection.commit() 或者
java.sql.Connection.rollback() .
相反,應(yīng)用程序應(yīng)該使用 UserTransaction.begin()、 UserTransaction.commit() 和 serTransaction.rollback() .
3.容器事務(wù)
容器事務(wù)主要是J2EE應(yīng)用服務(wù)器提供的,容器事務(wù)大多是基于JTA完成,這是一個(gè)基于JNDI的,相當(dāng)復(fù)雜的API實(shí)現(xiàn)。相對(duì)編碼實(shí)現(xiàn)JTA事務(wù)管理,
我們可以通過(guò)EJB容器提供的容器事務(wù)管理機(jī)制(CMT)完成同一個(gè)功能,這項(xiàng)功能由J2EE應(yīng)用服務(wù)器提供。這使得我們可以簡(jiǎn)單的指定將哪個(gè)方法加入事
務(wù),一旦指定,容器將負(fù)責(zé)事務(wù)管理任務(wù)。這是我們土建的解決方式,因?yàn)橥ㄟ^(guò)這種方式我們可以將事務(wù)代碼排除在邏輯編碼之外,同時(shí)將所有困難交給J2EE容
器去解決。使用EJB CMT的另外一個(gè)好處就是程序員無(wú)需關(guān)心JTA API的編碼,不過(guò),理論上我們必須使用EJB.
三種Java事務(wù)差異?
1、JDBC事務(wù)控制的局限性在一個(gè)數(shù)據(jù)庫(kù)連接內(nèi),但是其使用簡(jiǎn)單。
2、JTA事務(wù)的功能強(qiáng)大,事務(wù)可以跨越多個(gè)數(shù)據(jù)庫(kù)或多個(gè)DAO,使用也比較復(fù)雜。
3、容器事務(wù),主要指的是J2EE應(yīng)用服務(wù)器提供的事務(wù)管理,局限于EJB應(yīng)用使用。
五、總結(jié)
Java事務(wù)控制是構(gòu)建J2EE應(yīng)用不可缺少的一部分,合理選擇應(yīng)用何種事務(wù)對(duì)整個(gè)應(yīng)用系統(tǒng)來(lái)說(shuō)至關(guān)重要。一般說(shuō)來(lái),在單個(gè)JDBC
連接連接的情況下可以選擇JDBC事務(wù),在跨多個(gè)連接或者數(shù)據(jù)庫(kù)情況下,需要選擇使用JTA事務(wù),如果用到了EJB,則可以考慮使用EJB容器事務(wù)。
事務(wù)(Transaction):是并發(fā)控制的單元,是用戶(hù)定義的一個(gè)操作序列。這些操作要么都做,要么都不做,是一個(gè)不可分割的工作單位。通過(guò)事務(wù),sql server 能將邏輯相關(guān)的一組操作綁定在一起,以便服務(wù)器 保持?jǐn)?shù)據(jù)的完整性。事務(wù)通常是以begin transaction開(kāi)始,以commit或rollback結(jié)束。Commint表示提交,即提交事務(wù)的所有操作。具體地說(shuō)就是將事務(wù)中所有對(duì)數(shù)據(jù)的更新
寫(xiě)回到磁盤(pán)上的物理數(shù)據(jù)庫(kù)中去,事務(wù)正常結(jié)束。Rollback表示回滾,即在事務(wù)運(yùn)行的過(guò)程中發(fā)生了某種故障,事務(wù)不能繼續(xù)進(jìn)行,系統(tǒng)將事務(wù)中對(duì)數(shù)據(jù)庫(kù)的所有已完成的操作全部撤消,滾回到事務(wù)開(kāi)始的狀態(tài)。
自動(dòng)提交事務(wù):每條單獨(dú)的語(yǔ)句都是一個(gè)事務(wù)。每個(gè)語(yǔ)句后都隱含一個(gè)commit。 (默認(rèn))
顯式事務(wù):以begin transaction顯示開(kāi)始,以commit或rollback結(jié)束。
隱式事務(wù):當(dāng)連接以隱式事務(wù)模式進(jìn)行操作時(shí),sql server數(shù)據(jù)庫(kù)引擎實(shí)例將在提交或回滾當(dāng)前事務(wù)后自動(dòng)啟動(dòng)新事務(wù)。無(wú)須描述事物的開(kāi)始,只需提交或回滾每個(gè)事務(wù)。但每個(gè)事務(wù)仍以commit或rollback顯式結(jié)束。連接將隱性事務(wù)模式設(shè)置為打開(kāi)之后,當(dāng)數(shù)據(jù)庫(kù)引擎實(shí)例首次執(zhí)行下列任何語(yǔ)句時(shí),都會(huì)自動(dòng)啟動(dòng)一個(gè)隱式事務(wù):alter table,insert,create,open ,delete,revoke ,drop,select, fetch ,truncate table,grant,update在發(fā)出commit或rollback語(yǔ)句之前,該事務(wù)將一直保持有效。在第一個(gè)事務(wù)被提交或回滾之后,下次當(dāng)連接執(zhí)行以上任何語(yǔ)句時(shí),數(shù)據(jù)庫(kù)引擎實(shí)例都將自動(dòng)啟動(dòng)一個(gè)新事務(wù)。該實(shí)例將不斷地生成隱性事務(wù)鏈,直到隱性事務(wù)模式關(guān)閉為止。
Java JDBC事務(wù)機(jī)制
首先,我們來(lái)看看現(xiàn)有JDBC操作會(huì)給我們打來(lái)什么重大問(wèn)題,比如有一個(gè)業(yè)務(wù):當(dāng)我們修改一個(gè)信息后再去查詢(xún)這個(gè)信息,看是這是一個(gè)簡(jiǎn)單的業(yè)務(wù),實(shí)現(xiàn)起來(lái)也非常容易,但當(dāng)這個(gè)業(yè)務(wù)放在多線(xiàn)程高并發(fā)的平臺(tái)下,問(wèn)題自然就出現(xiàn)了,比如當(dāng)我們執(zhí)行了一個(gè)修改后,在執(zhí)行查詢(xún)之前有一個(gè)線(xiàn)程也執(zhí)行了修改語(yǔ)句,這是我們?cè)賵?zhí)行查詢(xún),看到的信息就有可能與我們修改的不同,為了解決這一問(wèn)題,我們必須引入JDBC事務(wù)機(jī)制,其實(shí)代碼實(shí)現(xiàn)上很簡(jiǎn)單,一下給出一個(gè)原理實(shí)現(xiàn)例子供大家參考:
1 private Connection conn = null;2
3 private PreparedStatement ps = null;4
5 try{6
7
8
9 conn.setAutoCommit(false); //將自動(dòng)提交設(shè)置為false
10
11 ps.executeUpdate("修改SQL"); //執(zhí)行修改操作
12
13 ps.executeQuery("查詢(xún)SQL"); //執(zhí)行查詢(xún)操作
14
15 conn.commit(); //當(dāng)兩個(gè)操作成功后手動(dòng)提交
16
17 } catch(Exception e) {18
19 conn.rollback(); //一旦其中一個(gè)操作出錯(cuò)都將回滾,使兩個(gè)操作都不成功
20
21 e.printStackTrace();22
23 }
與事務(wù)相關(guān)的理論
1.事務(wù)(Transaction)的四個(gè)屬性(ACID)
原子性(Atomic) 對(duì)數(shù)據(jù)的修改要么全部執(zhí)行,要么全部不執(zhí)行。
一致性(Consistent) 在事務(wù)執(zhí)行前后,數(shù)據(jù)狀態(tài)保持一致性。
隔離性(Isolated) 一個(gè)事務(wù)的處理不能影響另一個(gè)事務(wù)的處理。
持續(xù)性(Durable) 事務(wù)處理結(jié)束,其效果在數(shù)據(jù)庫(kù)中持久化。
2.事務(wù)并發(fā)處理可能引起的問(wèn)題
臟讀(dirty read):一個(gè)事務(wù)讀取了另一個(gè)事務(wù)尚未提交的數(shù)據(jù),
不可重復(fù)讀(non-repeatable read) :一個(gè)事務(wù)的操作導(dǎo)致另一個(gè)事務(wù)前后兩次讀取到不同的數(shù)據(jù)
幻讀(phantom read) :一個(gè)事務(wù)的操作導(dǎo)致另一個(gè)事務(wù)前后兩次查詢(xún)的結(jié)果數(shù)據(jù)量不同。
舉例:
事務(wù)A、B并發(fā)執(zhí)行時(shí),當(dāng)A事務(wù)update后,B事務(wù)select讀取到A尚未提交的數(shù)據(jù),此時(shí)A事務(wù)rollback,則B讀到的數(shù)據(jù)是無(wú)效的”臟”數(shù)據(jù)。
當(dāng)B事務(wù)select讀取數(shù)據(jù)后,A事務(wù)update操作更改B事務(wù)select到的數(shù)據(jù),此時(shí)B事務(wù)再次讀去該數(shù)據(jù),發(fā)現(xiàn)前后兩次的數(shù)據(jù)不一樣。
當(dāng)B事務(wù)select讀取數(shù)據(jù)后,A事務(wù)insert或delete了一條滿(mǎn)足A事務(wù)的select條件的記錄,此時(shí)B事務(wù)再次select,發(fā)現(xiàn)查詢(xún)到前次不存在的記錄(“幻影”),或者前次的某個(gè)記錄不見(jiàn)了。
JDBC的事務(wù)支持
JDBC對(duì)事務(wù)的支持體現(xiàn)在三個(gè)方面:
1.自動(dòng)提交模式(Auto-commit mode)
Connection提供了一個(gè)auto-commit的屬性來(lái)指定事務(wù)何時(shí)結(jié)束。
a.當(dāng)auto-commit為true時(shí),當(dāng)每個(gè)獨(dú)立SQL操作的執(zhí)行完畢,事務(wù)立即自動(dòng)提交,也就是說(shuō)每個(gè)SQL操作都是一個(gè)事務(wù)。一個(gè)獨(dú)立SQL操作什么時(shí)候算執(zhí)行完畢。
1.JDBC規(guī)范是這樣規(guī)定的:對(duì)數(shù)據(jù)操作語(yǔ)言(DML,如insert,update,delete)和數(shù)據(jù)定義語(yǔ)言(如create,drop),語(yǔ)句一執(zhí)行完就視為執(zhí)行完畢。2.對(duì)select語(yǔ)句,當(dāng)與它關(guān)聯(lián)的ResultSet對(duì)象關(guān)閉時(shí),視為執(zhí)行完畢。3.對(duì)存儲(chǔ)過(guò)程或其他返回多個(gè)結(jié)果的語(yǔ)句,當(dāng)與它關(guān)聯(lián)的所有ResultSet對(duì)象全部關(guān)閉,所有update count(update,delete等語(yǔ)句操作影響的行數(shù))和output parameter(存儲(chǔ)過(guò)程的輸出參數(shù))都已經(jīng)獲取之后,視為執(zhí)行完畢。
b. 當(dāng)auto-commit為false時(shí),每個(gè)事務(wù)都必須顯示調(diào)用commit方法進(jìn)行提交,或者顯示調(diào)用rollback方法進(jìn)行回滾。auto-commit默認(rèn)為true。
2.事務(wù)隔離級(jí)別(Transaction Isolation Levels)
JDBC提供了5種不同的事務(wù)隔離級(jí)別,在Connection中進(jìn)行了定義。
JDBC定義了五種事務(wù)隔離級(jí)別:
TRANSACTION_NONE JDBC驅(qū)動(dòng)不支持事務(wù)
TRANSACTION_READ_UNCOMMITTED 允許臟讀、不可重復(fù)讀和幻讀。
TRANSACTION_READ_COMMITTED 禁止臟讀,但允許不可重復(fù)讀和幻讀。
TRANSACTION_REPEATABLE_READ 禁止臟讀和不可重復(fù)讀,單運(yùn)行幻讀。
TRANSACTION_SERIALIZABLE 禁止臟讀、不可重復(fù)讀和幻讀。
3.保存點(diǎn)(SavePoint)
JDBC定義了SavePoint接口,提供在一個(gè)更細(xì)粒度的事務(wù)控制機(jī)制。當(dāng)設(shè)置了一個(gè)保存點(diǎn)后,可以rollback到該保存點(diǎn)處的狀態(tài),而不是rollback整個(gè)事務(wù)。
Connection接口的setSavepoint和releaseSavepoint方法可以設(shè)置和釋放保存點(diǎn)。
JDBC規(guī)范雖然定義了事務(wù)的以上支持行為,但是各個(gè)JDBC驅(qū)動(dòng),數(shù)據(jù)庫(kù)廠商對(duì)事務(wù)的支持程度可能各不相同。如果在程序中任意設(shè)置,可能得不到想要的效果。為此,JDBC提供了DatabaseMetaData接口,提供了一系列JDBC特性支持情況的獲取方法。比如,通過(guò)DatabaseMetaData.supportsTransactionIsolationLevel方法可以判斷對(duì)事務(wù)隔離級(jí)別的支持情況,通過(guò)DatabaseMetaData.supportsSavepoints方法可以判斷對(duì)保存點(diǎn)的支持情況。
總結(jié)
以上是生活随笔為你收集整理的java 事务_Java中事务总结详解(精华)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 无头是哪幅图?说名字
- 下一篇: 周易Java_周易API接口_免费数据接