摘要 本文介紹在Java中進行事務處理的方法,通過實例分別講述了如何采用JavaBean、Ejb組件實現J2EE應用服務器支持的JDBC事務、JTA(Java Transaction API)事務。
關鍵詞 JavaBean,EJB, 數據庫,事務處理,JTA
JavaBean
JavaBean是用Java語言編寫的與平台無關的組件。它是描述Java的軟件組件模型,有點類似於Microsoft的COM組件的概念。在Java模型中,通過JavaBean可以無限擴充Java程序的功能,通過JavaBean的組合可以快速的生成新的應用程序。JavaBean可以實現代碼的重復利用,對於程序的易維護性也有重大的意義。非可視化的JavaBean,在JSP程序中常用來封裝事務邏輯、數據庫操作等,可以很好的實現業務邏輯和前台程序的分離。JavaBean在服務器端的應用方面表現出了越來越強的生命力。
EJB
EJB技術定義了一組可重用的組件:Enterprise JavaBeans。你可以利用這些組件,像搭積木一樣的建立你的分布式應用程序。當你把代碼寫好之後,這些組件就被組合到特定的文件中去。每個文件有一個或多個Enterprise Beans,在加上一些配置參數。最後,這些Enterprise Beans被配置到一個裝了EJB容器的平台上。客戶能夠通過這些Beans的home接口,定位到某個beans,並產生這個beans的一個實例。這樣,客戶就能夠調用Beans的應用方法和遠程接口。EJB技術簡化了用JAVA語言編寫的企業應用系統的開發、配置和執行。有三種類型的Enterprise beans: Session beans、 entity beans和Message-driven Beans。
事務處理
信息是任何企事業單位的重要資產,任何企業部門都包含著信息的流入、流出,任何企業部門都控制著某些信息。同時,信息必須在適當的時機傳播給需要的人。而且,信息還需要安全約束,通常根據信息的類型和內容實施訪問控制。為了保證數據的安全有效和正確可靠,數據庫管理系統(DBMS)必須提供統一的數據保護功能。
事務是現代數據庫理論中的核心概念之一。如果一組處理步驟或者全部發生或者一步也不執行,我們稱該組處理步驟為一個事務。當所有的步驟像一個操作一樣被完整地執行,我們稱該事務被提交。由於其中的一部分或多步執行失敗,導致沒有步驟被提交,則事務必須回滾(回到最初的系統狀態)。事務必須服從ISO/IEC所制定的ACID原則。ACID是原子性(atomicity)、一致性(consistency)、隔離性(isolation)和持久性(durability)的縮寫。事務的原子性表示事務執行過程中的任何失敗都將導致事務所做的任何修改失效。一致性表示當事務執行失敗時,所有被該事務影響的數據都應該恢復到事務執行前的狀態。隔離性表示在事務執行過程中對數據的修改,在事務提交之前對其他事務不可見。持久性表示已提交的數據在事務執行失敗時,數據的狀態都應該正確。
在下面我們列舉一個使用SQL Server數據庫進行事務處理的例子。主表是一個規章制度信息表(bylaw),主要字段有記錄編號、標題、作者、書寫日期等。兩個子表分別是附件表(bylaw_affix)和文本信息表(bylaw_content)。表結構見圖1所示。bylaw表的記錄編號與bylaw_affix表的記錄編號、bylaw_content表的記錄編號是對應的,每次對規章制度信息的操作也就是對這三個表的聯合操作。例如要刪除規章制度中的一條記錄,如果不使用事務,就可能會出現這樣的情況:第一個表中成功刪除後,數據庫突然出現意外狀況,而第二、三個表中的操作沒有完成,這樣,刪除操作並沒有完成,甚至已經破壞數據庫中的數據。要避免這種情況,就應該使用事務,它的作用是:要麼三個表都操作成功,要麼都失敗。換句話說,就是保持數據的一致性。所以,為了確保對數據操作的完整和一致,在程序設計時要充分考慮到事務處理方面的問題。
圖1 示例表結構
Java中的事務處理
一般情況下,J2EE應用服務器支持JDBC事務、JTA(Java Transaction API)事務、容器管理事務。一般情況下,最好不要在程序中同時使用上述三種事務類型,比如在JTA事務中嵌套JDBC事務。第二方面,事務要在盡可能短的時間內完成,不要在不同方法中實現事務的使用。下面我們列舉兩種事務處理方式。
1、JavaBean中使用JDBC方式進行事務處理
在JDBC中怎樣將多個SQL語句組合成一個事務呢?在JDBC中,打開一個連接對象Connection時,缺省是auto-commit模式,每個SQL語句都被當作一個事務,即每次執行一個語句,都會自動的得到事務確認。為了能將多個SQL語句組合成一個事務,要將auto-commit模式屏蔽掉。在auto-commit模式屏蔽掉之後,如果不調用commit()方法,SQL語句不會得到事務確認。在最近一次commit()方法調用之後的所有SQL會在方法commit()調用時得到確認。
public int delete(int sID) {
dbc = new DataBaseConnection();
Connection con = dbc.getConnection();
try {
con.setAutoCommit(false);// 更改JDBC事務的默認提交方式
dbc.executeUpdate("delete from bylaw where ID=" + sID);
dbc.executeUpdate("delete from bylaw _content where ID=" + sID);
dbc.executeUpdate("delete from bylaw _affix where bylawid=" + sID);
con.commit();//提交JDBC事務
con.setAutoCommit(true);// 恢復JDBC事務的默認提交方式
dbc.close();
return 1;
}
catch (Exception exc) {
con.rollBack();//回滾JDBC事務
exc.printStackTrace();
dbc.close();
return -1;
}
}
2、SessionBean中的JTA事務
JTA 是事務服務的 J2EE 解決方案。本質上,它是描述事務接口(比如 UserTransaction 接口,開發人員直接使用該接口或者通過 J2EE 容器使用該接口來確保業務邏輯能夠可靠地運行)的 J2EE 模型的一部分。JTA 具有的三個主要的接口分別是 UserTransaction 接口、TransactionManager 接口和 Transaction 接口。這些接口共享公共的事務操作,例如 commit() 和 rollback(), 但是也包含特殊的事務操作,例如 suspend(),resume() 和 enlist(),它們只出現在特定的接口上,以便在實現中允許一定程度的訪問控制。例如,UserTransaction 能夠執行事務劃分和基本的事務操作,而 TransactionManager 能夠執行上下文管理。
應用程序可以調用UserTransaction.begin()方法開始一個事務,該事務與應用程序正在其中運行的當前線程相關聯。底層的事務管理器實際處理線程與事務之間的關聯。UserTransaction.commit()方法終止與當前線程關聯的事務。UserTransaction.rollback()方法將放棄與當前線程關聯的當前事務。
public int delete(int sID) {
DataBaseConnection dbc = null;
dbc = new DataBaseConnection();
dbc.getConnection();
UserTransaction transaction = sessionContext.getUserTransaction();//獲得JTA事務
try {
transaction.begin(); //開始JTA事務
dbc.executeUpdate("delete from bylaw where ID=" + sID);
dbc.executeUpdate("delete from bylaw _content where ID=" + sID);
dbc.executeUpdate("delete from bylaw _affix where bylawid=" + sID);
transaction.commit(); //提交JTA事務
dbc.close();
return 1;
}
catch (Exception exc) {
try {
transaction.rollback();//JTA事務回滾
}
catch (Exception ex) {
//JTA事務回滾出錯處理
ex.printStackTrace();
}
exc.printStackTrace();
dbc.close();
return -1;
}
}