Cool eye

          BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
            63 Posts :: 4 Stories :: 3 Comments :: 0 Trackbacks

          第14章 事務(wù)

          Dale Green著

          JSP WU 譯

          一個典型的企業(yè)應(yīng)用程序在一個或多個數(shù)據(jù)庫中訪問和存儲信息。因為這些信息對于商業(yè)操作非常重要,它必須精確、實時、可靠。如果允許多個程序同時更新相同的數(shù)據(jù),就會破壞數(shù)據(jù)的完整性。如果在一個商業(yè)交易處理過程中,部分數(shù)據(jù)被更新后系統(tǒng)崩潰也將破壞數(shù)據(jù)完整性。事務(wù)通過預防以上情況的發(fā)生確保數(shù)據(jù)的完整性。事務(wù)控制多個應(yīng)用程序?qū)?shù)據(jù)庫的并發(fā)操作。如果發(fā)生系統(tǒng)崩潰,事務(wù)確保恢復的數(shù)據(jù)崩潰前將保持一致。

          本章內(nèi)容:

          什么是事務(wù)

          容器管理事務(wù)

          事務(wù)的屬性

          回滾容器管理事務(wù)

          同步會話bean實例變量

          容器管理事務(wù)中不允許使用的方法

          Bean 管理事務(wù)

          JDBC事務(wù)

          JTA? 事務(wù)

          非提交返回事務(wù)

          在Bean管理事務(wù)中不允許使用的方法

          企業(yè)Bean事務(wù)摘要

          事務(wù)超時

          隔離級別

          更新多個數(shù)據(jù)庫

          Web 組件事務(wù)

          ?

          一.什么是事務(wù)

          模擬一個商業(yè)交易,應(yīng)用程序需要完成幾個步驟。例如,一個財物應(yīng)用程序,可能會將資金從經(jīng)常性帳戶(checking account)轉(zhuǎn)到儲蓄性賬戶(saving account),該交易的偽碼表示如下:

          begin transaction

          debit checking account

          credit savings account

          update history log

          commit transaction

          三個步驟要么全部完成,要么一個都不做。否則數(shù)據(jù)完整性將被破壞。因為事務(wù)中的所有步驟被看作一個統(tǒng)一的整體,所以事務(wù)一般被定義為一個不可分割的工作單元。

          結(jié)束事務(wù)有兩種方法:提交或者回滾。當一個事務(wù)提交,數(shù)據(jù)修改被保存。如果事務(wù)中有一個步驟失敗,事務(wù)就回滾,這個事務(wù)中的已經(jīng)執(zhí)行的動作被撤銷。例如在上面的偽碼中,如果在處理第二步的時候硬盤驅(qū)動器崩潰,事務(wù)的第一步將被撤銷。盡管事務(wù)失敗,數(shù)據(jù)的完整性不會被破壞,因為帳目仍然保持平衡。

          前面?zhèn)未a中,begin和commit標明了事務(wù)的界限。當設(shè)計一個企業(yè)Bean的時候,你要決定怎樣通過容器管理或bean管理事務(wù)來指定事務(wù)界限。

          二.容器管理事務(wù)

          在容器管理事務(wù)的企業(yè)Bean中,EJB容器來設(shè)定事務(wù)界線。你能夠在任何企業(yè)Bean中使用容器管理事務(wù):會話Bean、實體Bean或者 Message-driven Bean。容器管理事務(wù)簡化了開發(fā),因為企業(yè)Bean不用編碼來顯式制定事務(wù)界限。代碼不包括開始結(jié)束事務(wù)的語句。典型的,容器會在一個企業(yè)Bean的方法被調(diào)用前立即開始一個事務(wù),在這個方法退出以前提交這個事務(wù)。每個方法都關(guān)聯(lián)一個事務(wù)。在一個方法中不允許嵌套或多個的事務(wù)存在。容器管理事務(wù)不需要所有的方法都關(guān)聯(lián)事務(wù)。當部署一個Bean時,通過設(shè)定部署描述符中的事務(wù)屬性來決定方法是否關(guān)聯(lián)事務(wù)和如何關(guān)聯(lián)事務(wù)。

          事務(wù)的屬性

          一個事務(wù)的屬性控制了事務(wù)的使用范圍。圖 14-1說明了為什么控制事務(wù)的范圍很重要。圖中,method-A開始一個事務(wù)然后調(diào)用Bean-2中的method-B.它運行在method-A開始的事務(wù)中還是重新執(zhí)行一個新的事務(wù)?結(jié)果要看method-B中的事務(wù)屬性。

          圖 14-1 Transaction Scope

          一個事務(wù)屬性可能有下面的屬性之一:

          ☆ Required

          ☆ RequiresNew

          ☆ Mandatory

          ☆ NotSupported

          ☆ Supports

          ☆ Never

          Required

          如果客戶端正在一個運行的事務(wù)中調(diào)用一個企業(yè)Bean的方法,這個方法就在這個客戶端的事務(wù)中執(zhí)行。如果客戶端不關(guān)聯(lián)一個事務(wù),這個容器在運行該方法前開始一個新的事務(wù)。

          Required屬性在許多事務(wù)環(huán)境中可以很好的工作,因此你可以把它作為一個默認值,至少可以在早期開發(fā)中使用。因為事務(wù)的屬性是在部署描述符中聲明的,在以后的任何時候修改它們都很容易。

          RequiresNew

          如果客戶端在一個運行的事務(wù)中調(diào)用企業(yè)Bean的方法,容器的步驟是:

          1.掛起客戶端的事務(wù)

          2.開始一個新的事務(wù)

          3.代理方法的調(diào)用

          4.方法完成后重新開始客戶端的事務(wù)

          如果客戶端不關(guān)聯(lián)一個事務(wù),容器運行這個方法以前同樣開始一個新的事務(wù)。如果你想保證該方法在任何時候都在一個新事物中運行,使用RequiresNew屬性。

          Mandatory

          如果客戶端在一個運行的事務(wù)中調(diào)用企業(yè)Bean的方法,這個方法就在客戶端的事務(wù)中執(zhí)行。如果客戶端不關(guān)聯(lián)事務(wù),容器就拋出TransactionRequiredException 異常。

          如果企業(yè)Bean的方法必須使用客戶端的事務(wù),那么就使用Mandatory屬性。

          NotSupported

          如果客戶端在一個運行的事務(wù)中調(diào)用企業(yè)Bean的方法,這個容器在調(diào)用該方法以前掛起客戶端事務(wù)。方法執(zhí)行完后,容器重新開始客戶端的事務(wù)。

          如果客戶端不關(guān)聯(lián)事務(wù),容器在方法運行以前不會開始一個新的事務(wù)。為不需要事務(wù)的方法使用NotSupported屬性。因為事務(wù)包括整個過程,這個屬性可以提高性能。

          Supports

          如果客戶端在一個運行的事務(wù)中調(diào)用企業(yè)Bean的方法,這個方法在客戶端的事務(wù)中執(zhí)行,如果這個客戶端不關(guān)聯(lián)一個事務(wù),容器運行該方法前也不會開始一個新的事務(wù)。因為該屬性使方法的事務(wù)行為不確定,你應(yīng)該謹慎使用Supports屬性。

          Never

          如果客戶端在一個運行的事務(wù)中調(diào)用企業(yè)Bean的方法,容器將拋出RemoteException異常。如果這個客戶端不關(guān)聯(lián)一個事務(wù),容器運行該方法以前不會開始一個新的事務(wù)。

          Summary of Transaction Attributes(事務(wù)屬性概要)

          表 14-1 列出了事務(wù)屬性的影響。事務(wù)T1和T2都被容器控制。T1是調(diào)用企業(yè)Bean方法的客戶端的事務(wù)環(huán)境。在大多數(shù)情況下,客戶端是其它的企業(yè)Bean。T2是在方法執(zhí)行以前容器啟動的事務(wù)。在表 14-1中,“None”的意思是這個商業(yè)方法不在容器控制事務(wù)中執(zhí)行。然而,該商業(yè)方法中的數(shù)據(jù)庫操作可能在DBMS管理控制的事務(wù)中執(zhí)行。

          Setting Transaction Attributes (設(shè)定事務(wù)屬性)

          因為事務(wù)屬性被保存在配置描述符中,他們會在J2EE應(yīng)用程序開發(fā)的幾個階段被改變:創(chuàng)建企業(yè)Bean,應(yīng)用程序裝配和部署。然而, 當創(chuàng)建這個Bean的時候指定它的屬性是企業(yè)Bean開發(fā)者的責任。只有將該組件裝配到一個更大的應(yīng)用程序時可以由開發(fā)者修改該屬性,而不要期待J2EE應(yīng)用程序部署者來指定該事務(wù)屬性。

          表 14-1 事物屬性和范圍?

          事務(wù)屬性

          客戶端事務(wù)

          商業(yè)方法事務(wù)

          Required

          None

          T2

          T1

          T1

          RequiresNew

          None

          T2

          T1

          T2

          Mandatory

          None

          error

          T1

          T1

          NotSupported

          None

          None

          T1

          None

          Supports

          None

          None

          T1

          T1

          Never

          None

          None

          T1

          Error

          你可以為整個企業(yè)Bean或者單個方法指定事務(wù)屬性。如果你為整個企業(yè)Bean和它某個方法各指定一個事務(wù)屬性,為該方法指定的事務(wù)屬性優(yōu)先。當為單個方法指定事務(wù)屬性時,不同類型企業(yè)Bean的要求也不同。會話Bean需要為商業(yè)方法定義屬性屬性,但create方法不需要定義事務(wù)屬性。實體Bean需要為商業(yè)方法、create方法、remove方法和查找(finder)方法定義事務(wù)屬性。Message-driven Bean需要為onMessage方法指定屬性事務(wù),而且只能是Required和NotSupported其中之一。

          容器管理事務(wù)的回滾

            在以下兩中情況下,事務(wù)將回滾。第一,如果產(chǎn)生一個系統(tǒng)異常,容器將自動回滾該事務(wù)。第二,通過調(diào)用EJBContext接口SetRollbackOnly方法,Bean方法通知容器回滾該事務(wù)。如果Bean拋出一個應(yīng)用異常,事務(wù)將不會自動回滾,但可以調(diào)用SetRollbackOnly回滾。對于一個系統(tǒng)和應(yīng)用的異常,參考第5章的處理異常一節(jié)。

          下面這個例子的代碼在j2eetorial/examples/src/bank目錄下。在命令行窗口下進入j2eetutorial/examples目錄執(zhí)行ant bank命令編譯這些代碼,執(zhí)行 ant create-bank-table命令創(chuàng)建要用到的表。一個BankApp.ear樣本文件在j2eetutorial/examples/ears目錄下。通過BnankEJB 實例的transferToSaving方法來說明setRollbackOnly方法的用法。如果余額檢查出現(xiàn)負數(shù),那么transferToSaving調(diào)用setRollBackOnly回滾事務(wù)并拋出一個應(yīng)用程序異常(InsufficientBalanceException)。updateChecking和updateSaving 方法更新數(shù)據(jù)表。如果更新失敗,這兩個方法拋出SQLException異常而transgerToSaving方法拋出EJBException異常。因為EJBException是一個系統(tǒng)異常,它使容器事務(wù)自動回滾事務(wù)。TransferTuSaving 方法的代碼如下:

          public void transferToSaving(double amount) throws

          ?? InsufficientBalanceException? {

          ? checkingBalance -= amount;

          ?? savingBalance += amount;

          ? try {

          ???? ?updateChecking(checkingBalance);

          ????? if (checkingBalance < 0.00) {

          ???????? context.setRollbackOnly();

          ???????? throw new InsufficientBalanceException();

          ????? }

          ????? updateSaving(savingBalance);

          ?? } catch (SQLException ex) {

          ?????? throw new EJBException

          ??????????("Transaction failed due to SQLException: "

          ??????????+ ex.getMessage());

          ?? }

          }

          當一個容器回滾一個事務(wù),它總是會撤消事務(wù)中已執(zhí)行的SQL語句造成的數(shù)據(jù)改動。然而,僅僅在實體Bean中容器回滾才會改變Bean的實例變量(與數(shù)據(jù)庫狀態(tài)有關(guān)的字段)。(這是因為容器會自動調(diào)用實體Bean的ejbLoad方法,該方法從數(shù)據(jù)庫中讀入實例變量的值。)當發(fā)生回滾,會話Bean必須顯式重新設(shè)置所有被事務(wù)改動過的實例變量。重設(shè)會話Bean的實例變量最簡單的方法是實現(xiàn)SessionSynchronization接口。

          同步會話Bean的實例變量

          SessionSynchronization接口是可選的,它允許你在Bean的實例變量和它們在數(shù)據(jù)庫中的相應(yīng)值之間保持同步。容器會在事務(wù)的幾個主要階段調(diào)用SessionSynchronization接口的對應(yīng)方法—afterBegin、beforeCompletion和afterCompletion。

          AfterBegin方法通知Bean實例一個新的事務(wù)已經(jīng)開始。容器在調(diào)用商業(yè)方法以前立即調(diào)用afterBegin方法。afterBegin方法是從數(shù)據(jù)庫中讀入實例變量值的最佳位置。例如,在BanBean類中,在afterBegin方法中從讀入了CheckingBalance和savingBalance變量的值:

          ? public void afterBegin() {

          ? System.out.println("afterBegin()");

          ?? try {

          ????? checkingBalance = selectChecking();

          ????? savingBalance = selectSaving();

          ?? } catch (SQLException ex) {

          ?????? throw new EJBException("afterBegin Exception: " +

          ?????????? ex.getMessage());

          ?? }

          }

          商業(yè)方法方法完成以后,容器調(diào)用beforeCompletion方法,不過僅僅是在事務(wù)提交以前。BeforeCompletion方法是會話Bean回滾事務(wù)的最后時機(通過調(diào)用setRollbackOnly方法).如果會話Bean還沒有實例變量的值更新數(shù)據(jù)庫,就在beforCompletion方法里實現(xiàn)。

          afterCompletion方法指出事務(wù)已經(jīng)完成。它只有一個布爾型的參數(shù),true表示事務(wù)被正確提交false表示事務(wù)回滾。如果事務(wù)回滾,會話Bean可以在該方法中從數(shù)據(jù)庫中重新讀取它的實例變量值:

          public void afterCompletion(boolean committed) {

          ? System.out.println("afterCompletion: " + committed);

          ?? if (committed == false) {

          ????? try {

          ???????? checkingBalance = selectChecking();

          ???????? savingBalance = selectSaving();

          ????? } catch (SQLException ex) {

          ????????? throw new EJBException("afterCompletion SQLException:

          ???????? " + ex.getMessage());

          ????? }

          ?? }

          }

          容器管理事務(wù)中不允許使用的方法

          你不應(yīng)該調(diào)用可能干擾容器設(shè)置的事務(wù)界線的方法,下面列出了所有禁止的方法:

          ☆ java.sql.Connection接口的commit、setAutoCommit和rollback方法

          ☆ javax.ejb.EJBContext 接口的getUserTransaction方法

          ☆ javax.transaction.UserTransaction接口的所有方法

          然而你可以在Bean管理事務(wù)中使用這些方法設(shè)置事務(wù)界限。

          三.Bean管理事務(wù)

          在一個Bean管理事務(wù)中,會話Bean或者Message-driven Bean是用代碼顯式設(shè)置事務(wù)界線的。實體Bean不能使用Bean管理事務(wù),只能使用容器管理的事務(wù)。雖然容器管理事務(wù)Bean需要較少的代碼,但它也有一個局限:方法執(zhí)行時,它只能關(guān)聯(lián)一個事務(wù)或不關(guān)聯(lián)任何事務(wù)。如果這個局限使你Bean編碼困難,你應(yīng)該考慮使用Bean管理事務(wù)。(譯者:實際上J2EE服務(wù)器不支持嵌套事物,那么Bean管理事務(wù)唯一的優(yōu)點就是可以在一個方法中一次啟動多個事務(wù))

          下面的偽碼很好說明了Bean管理事對商業(yè)邏輯的緊密控制。通過檢查各種條件,偽碼決定是否在商業(yè)方法中啟動或停止不同的事務(wù)。

          begin transaction

          ...

          update table-a

          ...

          if (condition-x)

          ?? commit transaction

          else if (condition-y)

          ?? update table-b

          ?? commit transaction

          else

          ?? rollback transaction

          ?? begin transaction

          ?? update table-c

          ?? commit transaction

          當為會話Bean或Message-driver Bean的Bean管理事務(wù)編碼時,你必須決定是使用jdbc或者JTA事務(wù)。下面的內(nèi)容論述了兩種事務(wù)類型。

          JDBC 事務(wù)

          JDBC事務(wù)通過DBMS事務(wù)管理器來控制。你可能會為了使用會話Bean中的原有代碼而采用JDBC事務(wù)將這些代碼封裝到一個事務(wù)中。使用JDBC事務(wù),要調(diào)用java.sql.Connection接口的commit和rollback方法。事務(wù)啟動是隱式的。一個事務(wù)的從最近的提交、回滾或連接操作后的第一個SQL的語句開始。(這個規(guī)則通常是正確的,但可能DBMS廠商的不同而不同)

          代碼資源

          下面的例子在j2eetutorial/examples/src/ejb/warehouse目錄下。在命令行窗口中進入j2eetutorial/examples目錄執(zhí)行ant bank命令編譯這些源文件,執(zhí)行ant create-warehouse-table命令創(chuàng)建要用到的表,一個樣本W(wǎng)arehouseApp.ear文件在j2eetutorial/example/ears 目錄下。

          下面的代碼來自WarehouseEJB例子,一個會話Bean通過使用Connection接口的方法來劃定Bean管理事務(wù)界限。ship方法以調(diào)用名為con的連接對象的setAutoCommit方法開始,該方法通知DBMS不要自動提交每個SQL語句。接下來ship 方法更新order_item和inventory數(shù)據(jù)表。如果更新成功,這個事務(wù)就會被提交。如果出現(xiàn)異常,事務(wù)就回滾。

          public void ship (String productId, String orderId, int

          quantity) {

          ? try {

          ????? con.setAutoCommit(false);

          ????? updateOrderItem(productId, orderId);

          ????? updateInventory(productId, quantity);

          ????? con.commit();

          ?? } catch (Exception ex) {

          ?????? try {

          ????????? con.rollback();

          ????????? throw new EJBException("Transaction failed: " +

          ???????????? ex.getMessage());

          ?????? } catch (SQLException sqx) {

          ?????????? throw new EJBException("Rollback failed: " +

          ????????????? sqx.getMessage());

          ?????? }

          ?? }

          }

          JTA 事務(wù)

          JTA是Java Transaction API 的縮寫。這些API 允許你用獨立于具體的事務(wù)管理器實現(xiàn)的方法確定事務(wù)界限。J2EE SDK 事務(wù)管理器通過Java事務(wù)服務(wù)(Java Transaction Service, JTS)實現(xiàn)。但是你的代碼并不直接調(diào)用JTS中的方法,而是調(diào)用JTA方法來替代,JTA方法會調(diào)用底層的JTS實現(xiàn)。

          JTA事務(wù)被J2EE?事務(wù)管理器管理。你可能需要使用一個JTA事務(wù),因為它能夠統(tǒng)一操作不同廠商的數(shù)據(jù)庫。一個特定DBMS的事務(wù)管理器不能工作在不同種類的數(shù)據(jù)庫上。然而J2EE事務(wù)管理器仍然有一個限制——它不支持嵌套事務(wù)。就是說,它不能在前一個事務(wù)結(jié)束前啟動另一個事務(wù)。

          下面例子的源代碼在j2eetutorial/examples/src/ejb/teller目錄下,在命令行窗口進入j2eetutorial/examples目錄,執(zhí)行ant teller命令編譯這些源文件,執(zhí)行ant create-bank-teller命令創(chuàng)建要用到的表。一個樣本TellerApp.ear文件在j2eetutorial/examples/ears目錄下。

          要自己確定事務(wù)界限,可以調(diào)用javax.transaction.UserTransaction接口的begin、commit和rollback方法來確定事務(wù)界限(該接口只能在SessionBean中使用,實體Bean不允許使用用戶自定義的)。下面選自TellerBean類的代碼示范了UserTransaction的用法。begin和commit方法確定了數(shù)據(jù)庫操作的事務(wù)界限,如果操作失敗則調(diào)用rollback回滾事務(wù)并拋出EJBException異常。

          public void withdrawCash(double amount) {

          ? UserTransaction ut = context.getUserTransaction();

          ? try {

          ????? ut.begin();

          ????? updateChecking(amount);

          ????? machineBalance -= amount;

          ????? insertMachine(machineBalance);

          ????? ut.commit();

          ?? } catch (Exception ex) {

          ?????? try {

          ????? ????ut.rollback();

          ?????? } catch (SystemException syex) {

          ?????????? throw new EJBException

          ????????????? ("Rollback failed: " + syex.getMessage());

          ?????? }

          ?????? throw new EJBException

          ????????? ("Transaction failed: " + ex.getMessage());

          ??? }

          }

          非提交返回事務(wù)

          使用Bean管理事務(wù)的無狀態(tài)會話Bean在事務(wù)返回前必須提交或者返回事務(wù),而有狀態(tài)的會話Bean沒有這個限制。

          對于使用JTA事務(wù)的有狀態(tài)會話Bean,Bean實例和事務(wù)的關(guān)聯(lián)越過大量用戶調(diào)用被保持,甚至被調(diào)用的每個商業(yè)方法都打開和關(guān)閉數(shù)據(jù)庫連接,該市無關(guān)聯(lián)也不斷開,直到事務(wù)完成(或回滾)。

          對于使用JDBC事務(wù)的有狀態(tài)會話Bean,JDBC連接越過用戶調(diào)用保持Bean和事務(wù)之間的關(guān)聯(lián)。連接關(guān)閉,事務(wù)關(guān)聯(lián)將被釋放。

          在Bean管理事務(wù)中不允許使用的方法

          在Bean管理的事務(wù)中不能調(diào)用EJBContext接口的getRollbackOnly和setRollbackOnly方法,這兩個方法只能在容器管理事務(wù)中被調(diào)用。在Bean管理事務(wù)中,應(yīng)調(diào)用UserTransaction接口的getStatus和rollback方法。

          四.企業(yè)Bean事務(wù)摘要

          如果你不能確定怎么在企業(yè)Bean中使用事務(wù),可以用這個小技巧:在Bean的部署描述符中,制定事務(wù)類型為容器管理,把整個Bean(所有方法)的事務(wù)屬性設(shè)置為Required。大多數(shù)情況下,這個配置可以滿足你的事務(wù)需求。

          表14-2列出了不同類型的企業(yè)Bean所允許使用的事務(wù)類型。實體Bean只能使用容器管理事務(wù),但可以在部署描述符中配置事務(wù)屬性,并可以調(diào)用EJBContext接口的setRollbackOnly方法來回滾事務(wù)。

          表 14-2 企業(yè)Bean 允許的事務(wù)類型

          企業(yè)Bean 類型

          容器管理事務(wù)

          Bean管理事務(wù)

          ?

          JTA

          JDBC

          ?

          實體Bean

          Y

          N

          N

          ?

          會話Bean

          Y

          Y

          Y

          ?

          Message-driven

          Y

          Y

          Y

          ?

          會話Bean既可以使用容器管理事務(wù)也可以使用Bean管理事務(wù)。Bean管理事務(wù)又有兩種類型:JDBC事務(wù)和JTA事務(wù)。JDBC事務(wù)使用Connection接口的commit和rollback方法來劃分事務(wù)界限。JTA事務(wù)使用UserTransaction接口的begin、commit和rollback方法來劃分事務(wù)界限。

          在Bean管理事務(wù)的會話Bean中,混合使用JTA事務(wù)和JDBC事務(wù)是可能的。但是我不推薦這樣使用,因為這樣會造成代碼的調(diào)試和維護都很困難。

          Message-driver Bean和會話Bean一樣既可以使用容器管理事務(wù)也可以使用Bean管理事務(wù)。

          五.事務(wù)超時

          對于容器管理事務(wù),事務(wù)超時間隔是通過設(shè)置default.properties文件中ransaction.timeout屬性的值來確定的,該文件在J2EE SDK安裝目錄的config子目錄下。如下例將事務(wù)超時間隔設(shè)置為5秒鐘:

          transaction.timeout=5

          這樣,當事務(wù)在5秒鐘內(nèi)還沒有完成,容器將回滾該事務(wù)。

          J2EE SDK安裝后,超時間隔的缺省值為0,表示不計算超時,無論事務(wù)執(zhí)行多長時間,除非異常出錯回滾,一直等待事務(wù)完成。

          只有使用容器管理事務(wù)的企業(yè)Bean才會受到transaction.timeout屬性值的影響。Bean管理的JTA事務(wù)使用UserTransaction接口的setTransactionTimeout方法來設(shè)置事務(wù)超時間隔。

          六.隔離級別

          事務(wù)不僅保證事務(wù)界限內(nèi)的數(shù)據(jù)庫操作全部完成(或回滾)同時還隔離數(shù)據(jù)庫更新語句。隔離級別描述被修改的數(shù)據(jù)對其他事物的可見度。

          假如一個應(yīng)用程序在事務(wù)中修改一個顧客的電話號碼,在事務(wù)結(jié)束前另一個應(yīng)用程序要讀取該條記錄的電話號碼。那么第二個應(yīng)用程序是讀取修改過但還沒提交的數(shù)據(jù),還是讀取未修改前的老數(shù)據(jù)呢?答案就取決于事務(wù)的隔離級別。如果事務(wù)允許其他程序讀取未提交的數(shù)據(jù),會因為不用等待事務(wù)結(jié)束而提高性能,同時也有一個缺點,如果事務(wù)回滾,其他應(yīng)用程序讀取的將是錯誤的數(shù)據(jù)。

          容器管理持久性(CMP)的實體Bean的事務(wù)級別無法修改,它們使用DBMS的默認個理解別,通常是READ_COMMITTED。

          Bean管理持久性(BMP)的實體Bean和兩種會話Bean都可以通過在程序中調(diào)用底層DBMS提供的API來設(shè)置事務(wù)級別。例如,一個DBMS可能允許你如下調(diào)用setTransactionIsolation方法將隔離級別設(shè)置成可讀取未提交數(shù)據(jù):

          Connection con;

          ...

          con.setTransactionIsolation(TRANSACTION_READ_UNCOMMITTED);

          不要在事務(wù)執(zhí)行期間更改隔離級別,通常隔離級別的更改會引起DBMS產(chǎn)生一次隱式提交。因為隔離級別的控制會跟具體的DBMS廠商不同而不同,具體的信息請參考DBMS的文檔。J2EE平臺規(guī)范不包括隔離級別標準。

          七.更新多個數(shù)據(jù)庫

          J2EE事務(wù)管理器控制著除了Bean管理的JDBC事務(wù)以外的所有企業(yè)Bean事務(wù),它允許企業(yè)Bean在同一個事務(wù)中更新多個數(shù)據(jù)庫。下面示范在單個事務(wù)中更新多個數(shù)據(jù)庫的兩個應(yīng)用。

          圖14-2中,客戶端調(diào)用Bean-A的商業(yè)方法,商業(yè)方法啟動一個事務(wù),更新數(shù)據(jù)庫X和Y,Bean-A的商業(yè)方法有調(diào)用Bean-B的商業(yè)方法,Bean-B的商業(yè)方法更新數(shù)據(jù)庫Z然后返回事務(wù)的控制權(quán)給Bean-A的商業(yè)方法,由Bean-A提交該事務(wù)。三個數(shù)據(jù)庫的更新都在同一個事務(wù)中發(fā)生。

          圖 14-2 更新多個數(shù)據(jù)庫

          圖14-3中,客戶端調(diào)用Bean-A的商業(yè)方法,該商業(yè)方法啟動一個事務(wù)并更新數(shù)據(jù)庫X,然后調(diào)用另一個J2EE服務(wù)器中的Bean-B的方法,該方法更新數(shù)據(jù)庫Y。J2EE服務(wù)器保證兩個數(shù)據(jù)庫的更新都在同一個事務(wù)中進行(筆者認為應(yīng)該是第一個J2EE服務(wù)器的事務(wù)管理器管理整個事物)。

          圖 14-3 跨越J2EE服務(wù)器更新多個數(shù)據(jù)庫

          八.Web 組件事務(wù)

          Web組件中劃分事務(wù)界限可以使用java.sql.Connection接口和javax.transaction.UserTransaction接口中的任意一個。跟Bean管理事務(wù)的會話Bean使用一樣的兩個接口。這兩個接口的使用方法參考前面幾節(jié)的內(nèi)容。Web組件事務(wù)的例子在第10章Servlet技術(shù)第四節(jié)共享信息的訪問數(shù)據(jù)庫小節(jié)講述過。

          posted on 2006-10-20 16:39 joeyeezhang 閱讀(325) 評論(0)  編輯  收藏 所屬分類: Java
          主站蜘蛛池模板: 龙口市| 盐池县| 新干县| 新密市| 上栗县| 玉树县| 大安市| 岐山县| 金昌市| 温州市| 恩平市| 化州市| 望城县| 娄烦县| 阳谷县| 南昌市| 南汇区| 新乡县| 林甸县| 宿迁市| 玛曲县| 县级市| 忻城县| 鄂尔多斯市| 南宁市| 高淳县| 腾冲县| 姜堰市| 双流县| 襄垣县| 绥宁县| 微博| 长乐市| 富蕴县| 蒙城县| 榆树市| 武平县| 东明县| 桐庐县| 舒兰市| 岫岩|