引用http://dyldragon.javaeye.com/blog/789374
一、什么是Java事務(wù)
通常的觀念認(rèn)為,事務(wù)僅與數(shù)據(jù)庫相關(guān)。
事務(wù)必須服從ISO/IEC所制定的ACID原則。
ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)的縮寫。
事務(wù)的原子性表示事務(wù)執(zhí)行過程中的任何失敗都將導(dǎo)致事務(wù)所做的任何修改失效。
一致性表示當(dāng)事務(wù)執(zhí)行失敗時,所有被該事務(wù)影響的數(shù)據(jù)都應(yīng)該恢復(fù)到事務(wù)執(zhí)行前的狀態(tài)。
隔離性表示在事務(wù)執(zhí)行過程中對數(shù)據(jù)的修改,在事務(wù)提交之前對其他事務(wù)不可見。
持久性表示已提交的數(shù)據(jù)在事務(wù)執(zhí)行失敗時,數(shù)據(jù)的狀態(tài)都應(yīng)該正確。
通俗的理解,事務(wù)是一組原子操作單元,從數(shù)據(jù)庫角度說,就是一組SQL指令,要么全部執(zhí)行成功,若因?yàn)槟硞€原因其中一條指令執(zhí)行有錯誤,則撤銷先前執(zhí)行過的所有指令。更簡答的說就是:要么全部執(zhí)行成功,要么撤銷不執(zhí)行。
既然事務(wù)的概念從數(shù)據(jù)庫而來,那Java事務(wù)是什么?之間有什么聯(lián)系? 實(shí)際上,一個Java應(yīng)用系統(tǒng),如果要操作數(shù)據(jù)庫,則通過JDBC來實(shí)現(xiàn)的。增加、修改、刪除都是通過相應(yīng)方法間接來實(shí)現(xiàn)的,事務(wù)的控制也相應(yīng)轉(zhuǎn)移到Java程序代碼中。因此,數(shù)據(jù)庫操作的事務(wù)習(xí)慣上就稱為Java事務(wù)。
二、為什么需要事務(wù)
事務(wù)是為解決數(shù)據(jù)安全操作提出的,事務(wù)控制實(shí)際上就是控制數(shù)據(jù)的安全訪問。具一個簡單例子:比如銀行轉(zhuǎn)帳業(yè)務(wù),賬戶A要將自己賬戶上的1000 元轉(zhuǎn)到B賬戶下面,A賬戶余額首先要減去1000元,然后B賬戶要增加1000元。假如在中間網(wǎng)絡(luò)出現(xiàn)了問題,A賬戶減去1000元已經(jīng)結(jié)束,B因?yàn)榫W(wǎng)絡(luò)中斷而操作失敗,那么整個業(yè)務(wù)失敗,必須做出控制,要求A賬戶轉(zhuǎn)帳業(yè)務(wù)撤銷。這才能保證業(yè)務(wù)的正確性,完成這個操走就需要事務(wù),將A賬戶資金減少和B賬戶資金增加方到一個事務(wù)里面,要么全部執(zhí)行成功,要么操作全部撤銷,這樣就保持了數(shù)據(jù)的安全性。
三、Java事務(wù)的類型
Java 事務(wù)的類型有三種:JDBC事務(wù)、JTA(Java Transaction API)事務(wù)、容器事務(wù)。
1、JDBC事務(wù)
JDBC 事務(wù)是用 Connection 對象控制的。JDBC Connection 接口( java.sql.Connection )提供了兩種事務(wù)模式:自動提交和手工提交。 java.sql.Connection 提供了以下控制事務(wù)的方法:
public void setAutoCommit(boolean)
public boolean getAutoCommit()
public void commit()
public void rollback()
使用 JDBC 事務(wù)界定時,您可以將多個 SQL 語句結(jié)合到一個事務(wù)中。JDBC 事務(wù)的一個缺點(diǎn)是事務(wù)的范圍局限于一個數(shù)據(jù)庫連接。一個 JDBC 事務(wù)不能跨越多個數(shù)據(jù)庫。
2、JTA(Java Transaction API)事務(wù)
JTA 是一種高層的,與實(shí)現(xiàn)無關(guān)的,與協(xié)議無關(guān)的API,應(yīng)用程序和應(yīng)用服務(wù)器可以使用JTA來訪問事務(wù)。
JTA允許應(yīng)用程序執(zhí)行分布式事務(wù)處理--在兩個或多個網(wǎng)絡(luò)計(jì)算機(jī)資源上訪問并且更新數(shù)據(jù),這些數(shù)據(jù)可以分布在多個數(shù)據(jù)庫上。JDBC驅(qū)動程序的JTA支持極大地增強(qiáng)了數(shù)據(jù)訪問能力。
如果計(jì)劃用 JTA 界定事務(wù),那么就需要有一個實(shí)現(xiàn) javax.sql.XADataSource 、 javax.sql.XAConnection 和 javax.sql.XAResource接口的 JDBC 驅(qū)動程序。一個實(shí)現(xiàn)了這些接口的驅(qū)動程序?qū)⒖梢詤⑴c JTA 事務(wù)。一個 XADataSource 對象就是一個XAConnection 對象的工廠。 XAConnection s 是參與 JTA 事務(wù)的 JDBC 連接。
您將需要用應(yīng)用服務(wù)器的管理工具設(shè)置 XADataSource 。從應(yīng)用服務(wù)器和 JDBC 驅(qū)動程序的文檔中可以了解到相關(guān)的指導(dǎo)。
J2EE 應(yīng)用程序用 JNDI 查詢數(shù)據(jù)源。一旦應(yīng)用程序找到了數(shù)據(jù)源對象,它就調(diào)用 javax.sql.DataSource.getConnection() 以獲得到數(shù)據(jù)庫的連接。
XA 連接與非 XA 連接不同。一定要記住 XA 連接參與了 JTA 事務(wù)。這意味著 XA 連接不支持 JDBC 的自動提交功能。同時,應(yīng)用程序一定不要對 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完成,這是一個基于JNDI的,相當(dāng)復(fù)雜的API實(shí)現(xiàn)。相對編碼實(shí)現(xiàn)JTA 事務(wù)管理,我們可以通過EJB容器提供的容器事務(wù)管理機(jī)制(CMT)完成同一個功能,這項(xiàng)功能由J2EE應(yīng)用服務(wù)器提供。這使得我們可以簡單的指定將哪個方法加入事務(wù),一旦指定,容器將負(fù)責(zé)事務(wù)管理任務(wù)。這是我們土建的解決方式,因?yàn)橥ㄟ^這種方式我們可以將事務(wù)代碼排除在邏輯編碼之外,同時將所有困難交給 J2EE容器去解決。使用EJB CMT的另外一個好處就是程序員無需關(guān)心JTA API的編碼,不過,理論上我們必須使用EJB。
四、三種事務(wù)差異
1、JDBC事務(wù)控制的局限性在一個數(shù)據(jù)庫連接內(nèi),但是其使用簡單。
2、JTA事務(wù)的功能強(qiáng)大,事務(wù)可以跨越多個數(shù)據(jù)庫或多個DAO,使用也比較復(fù)雜。
3、容器事務(wù),主要指的是J2EE應(yīng)用服務(wù)器提供的事務(wù)管理,局限于EJB應(yīng)用使用。
JTA
Java事務(wù)API(JTA;Java Transaction API)和它的同胞Java事務(wù)服務(wù)(JTS;Java Transaction Service),為J2EE平臺提供了分布式事務(wù)服務(wù)。一個分布式事務(wù)(distributed transaction)包括一個事務(wù)管理器(transaction manager)和一個或多個資源管理器(resource manager)。一個資源管理器(resource manager)是任意類型的持久化數(shù)據(jù)存儲。事務(wù)管理器(transaction manager)承擔(dān)著所有事務(wù)參與單元者的相互通訊的責(zé)任。下圖顯示了事務(wù)管理器和資源管理的間的關(guān)系。
JTA事務(wù)比JDBC事務(wù)更強(qiáng)大。一個JTA事務(wù)可以有多個參與者,而一個JDBC事務(wù)則被限定在一個單一的數(shù)據(jù)庫連接。下列任一個Java平臺的組件都可以參與到一個JTA事務(wù)中:
JDBC連接
- JDO PersistenceManager 對象
- JMS 隊(duì)列
- JMS 主題
- 企業(yè)JavaBeans(EJB)
- 一個用J2EE Connector Architecture 規(guī)范編譯的資源分配器。
DAO
DAO是Data Access Object數(shù)據(jù)訪問接口,數(shù)據(jù)訪問:顧名思義就是與數(shù)據(jù)庫打交道。夾在業(yè)務(wù)邏輯與數(shù)據(jù)庫資源中間。對數(shù)據(jù)庫進(jìn)行CURD(增刪查改操作)。
在核心J2EE模式中是這樣介紹DAO模式的:為了建立一個健壯的J2EE應(yīng)用,應(yīng)該將所有對數(shù)據(jù)源的訪問操作抽象封裝在一個公共API中。用程序設(shè)計(jì)的語言來說,就是建立一個接口,接口中定義了此應(yīng)用程序中將會用到的所有事務(wù)方法。在這個應(yīng)用程序中,當(dāng)需要和數(shù)據(jù)源進(jìn)行交互的時候則使用這個接口,并且編寫一個單獨(dú)的類來實(shí)現(xiàn)這個接口在邏輯上對應(yīng)這個特定的數(shù)據(jù)存儲。
JDBC
JDBC(Java Data Base Connectivity,java數(shù)據(jù)庫連接)是一種用于執(zhí)行SQL語句的Java API,可以為多種關(guān)系數(shù)據(jù)庫提供統(tǒng)一訪問,它由一組用Java語言編寫的類和接口組成。JDBC為工具/數(shù)據(jù)庫開發(fā)人員提供了一個標(biāo)準(zhǔn)的API,據(jù)此可以構(gòu)建更高級的工具和接口,使數(shù)據(jù)庫開發(fā)人員能夠用純 Java API 編寫數(shù)據(jù)庫應(yīng)用程序,同時,JDBC也是個商標(biāo)名。
有了JDBC,向各種關(guān)系數(shù)據(jù)發(fā)送SQL語句就是一件很容易的事。換言之,有了JDBC API,就不必為訪問Sybase數(shù)據(jù)庫專門寫一個程序,為訪問Oracle數(shù)據(jù)庫又專門寫一個程序,或?yàn)樵L問Informix數(shù)據(jù)庫又編寫另一個程序等等,程序員只需用JDBC API寫一個程序就夠了,它可向相應(yīng)數(shù)據(jù)庫發(fā)送SQL調(diào)用。同時,將Java語言和JDBC結(jié)合起來使程序員不必為不同的平臺編寫不同的應(yīng)用程序,只須寫一遍程序就可以讓它在任何平臺上運(yùn)行,這也是Java語言“編寫一次,處處運(yùn)行”的優(yōu)勢。
簡單地說,JDBC 可做三件事:與數(shù)據(jù)庫建立連接、發(fā)送 操作數(shù)據(jù)庫的語句并處理結(jié)果。
JDO
JDO(Java Data Object )是一個JAVA用于存取某種數(shù)據(jù)倉庫中的對象的標(biāo)準(zhǔn)化API。JDO提供了透明的對象存儲,因此對開發(fā)人員來說,存儲數(shù)據(jù)對象完全不需要額外的代碼(如JDBC API的使用)。這些繁瑣的例行工作已經(jīng)轉(zhuǎn)移到JDO產(chǎn)品提供商身上,使開發(fā)人員解脫出來,從而集中時間和精力在業(yè)務(wù)邏輯上。另外,JDO很靈活,因?yàn)樗梢栽谌魏螖?shù)據(jù)底層上運(yùn)行。JDBC只是面向關(guān)系數(shù)據(jù)庫(RDBMS)JDO更通用,提供到任何數(shù)據(jù)底層的存儲功能,比如關(guān)系數(shù)據(jù)庫、文件、XML以及對象數(shù)據(jù)庫(ODBMS)等等,使得應(yīng)用可移植性更強(qiáng)。
JNDI
英文全稱是:Java Naming and Directory Interface
術(shù)語解釋:一組幫助做多個命名和目錄服務(wù)接口的API。
JNDI(Java Naming and Directory Interface)是SUN公司提供的一種標(biāo)準(zhǔn)的Java命名系統(tǒng)接口,JNDI提供統(tǒng)一的客戶端API,通過不同的訪問提供者接口JNDI SPI的實(shí)現(xiàn),由管理者將JNDI API映射為特定的命名服務(wù)和目錄系統(tǒng),使得Java應(yīng)用程序可以和這些命名服務(wù)和目錄服務(wù)之間進(jìn)行交互。集群JNDI實(shí)現(xiàn)了高可靠性JNDI[8],通過服務(wù)器的集群,保證了JNDI的負(fù)載平衡和錯誤恢復(fù)。在全局共享的方式下,集群中的一個應(yīng)用服務(wù)器保證本地JNDI樹的獨(dú)立性,并擁有全局的JNDI樹。每個應(yīng)用服務(wù)器在把部署的服務(wù)對象綁定到自己本地的JNDI樹的同時,還綁定到一個共享的全局JNDI樹,實(shí)現(xiàn)全局JNDI和自身JNDI的聯(lián)系。
JNDI(Java Naming and Directory Interface)是一個應(yīng)用程序設(shè)計(jì)的API,為開發(fā)人員提供了查找和訪問各種
命名和目錄服務(wù)的通用、統(tǒng)一的接口,類似JDBC都是構(gòu)建在抽象層上。
JNDI可訪問的現(xiàn)有的目錄及服務(wù)有:DNS、XNam 、Novell目錄服務(wù)、LDAP(Lightweight Directory Access Protocol 輕型目錄訪問協(xié)議)、 CORBA對象服務(wù)、文件系統(tǒng)、Windows XP/2000/NT/Me/9x的注冊表、RMI、
DSML v1&v2、NIS。
JNDI與JDBC
JNDI提供了一種統(tǒng)一的方式,可以用在網(wǎng)絡(luò)上查找和訪問服務(wù)。通過指定一個資源名稱,該名稱對應(yīng)于數(shù)據(jù)庫或命名服務(wù)中的一個記錄,同時返回?cái)?shù)據(jù)庫連接建立所必須的信息。
JNDI主要有兩部分組成:應(yīng)用程序編輯接口和服務(wù)供應(yīng)商接口。應(yīng)用程序編程接口提供了Java應(yīng)用程序訪問各種命名和目錄服務(wù)的功能,服務(wù)供應(yīng)商接口提供了任意一種服務(wù)的供應(yīng)商使用的功能。
- try{
- Context cntxt = new InitialContext();
- DataSource ds = (DataSource) cntxt.lookup("jdbc/dpt");
- }
- catch(NamingException ne){
- ...
- }