JavaEE事務,javaee

來源:互聯網
上載者:User

JavaEE事務,javaee
一、什麼是事務?事務(Transaction)是作為單個邏輯工作單元執行的一系列操作。這些操作作為一個整體向系統提交,要麼都執行、要麼都不執行。事務是一個不可分割的工作邏輯單元
轉賬操作A—>B:
begin transaction
1.更新帳戶A的餘額
2.記錄帳戶A的交易日誌
3.更新帳戶B的餘額
4.記錄帳戶B的交易日誌
end transaction


二、事務的特徵(ACID)原子性Atomicity
事務必須是原子工作單元。對於其資料修改,要麼全執行,要麼全都不執行。
一致性Consistency
事務在完成時,必須使所有的資料都保持一致狀態。在相關資料庫中,所有規則都必須應用於事務的修改,以保持所有資料的完整性。事務結束時,所有的內部資料結構都必須是正確的。在事務開始之前和事務結束以後,資料庫的完整性條件約束沒有被破壞。
隔離性Isolation
由並發事務所做的修改必須與任何其他並發事務所做的修改隔離。事務查看資料時資料所處的狀態,要麼是另一併發事務修改它之前的狀態,要麼是另一事務修改它之後的狀態,事務不會查看中間狀態的資料。
持久性Durability
事務完成之後,它對於系統的影響是永久性的: 該事務所對資料庫所作的更改便持久的儲存在資料庫之中,並不會被復原。


三、交易管理策略容器管理事務(CMT  Container Manage Transaction)
Bean管理事務(BMT Bean Manage Transaction )
JTA: Java Transaction API
1.JTA是JavaEE提供的管理分散式交易的一系列介面,它提供了TransactionManager和ResourceManager之間溝通機制。
a.javax.transaction.UserTransaction提供給應用程式代碼直接使用的介面,用於定義事務邊界和擷取事務狀態。
b.javax.transaction.TransactionManager主要由應用伺服器使用的介面,除了定義事務邊界和擷取事務狀態,還可以掛起(suspend)或者重啟(resume)事務。


四、事務屬性Required:
方法調用要求事務上下文,如果已經存在一個事務上下文,那麼就是用這個,如果不存在,則建立一個新的如果不存在新事務,容器啟動新的事務,如果存在事務,bean使用該事務。
RequiresNew:
容器在bean上的每個方法調用之前建立新事務,並在返回之前提交事務。調用bean方法的時候,總是啟動新事務。如果事務已經存在,則懸掛該事務,直到新事務完成。
NotSupported:
bean運行在事務內容相關的外部。在方法調用期間,懸掛起了現有事務。不能在事務內部調用bean。懸掛現有的事務,直到該bean中調用的方法完成。
Supports:
如果存在事務上下文,方法調用使用當前事務上下文。如果不存在,則不建立新的事務上下文。容器不啟動新的事務。如果事務已存在,bean將包含在這個事務中。
注意:使用這個屬性,沒有事務,bean也能運行。 
Mandatory:
方法調用需要事務上下文。如果不存在,拋出異常。必須已經存在活動事務。如果不存在事務,則拋出javax.ejb.TransactionRequiredException。 
Never:
方法調用要求不存在事務上下文。如果存在,則拋出異常。bean必須永遠不同事務同時運行。如果存在事務,則拋出java.rmi.RemoteException。

事務屬性-事務傳播

五、交易隔離等級目的:在資料庫操作中,為了有效保證並發讀取資料的正確性,提出的交易隔離等級。
問題:
更新丟失(Lost update)
兩個事務都同時更新一行資料,但是第二個事務卻中途失敗退出,導致對資料的兩個修改都失效了。這是因為系統沒有執行任何的鎖操作,因此並發事務並沒有被隔離開來。
髒讀(Dirty Reads)
一個事務開始讀取了某行資料,但是另外一個事務已經更新了此資料但沒有能夠及時提交。這是相當危險的,因為很可能所有的操作都被復原。
不可重複讀取(Non-repeatable Reads)
一個事務對同一行資料重複讀取兩次,但是卻得到了不同的結果。它包括以下情況: 
(1) 事務T1讀取某一資料後,事務T2對其做了修改,當事務T1再次讀該資料時得到與前一次不同的值。 
(2) 幻讀(Phantom Reads):事務在操作過程中進行兩次查詢,第二次查詢的結果包含了第一次查詢中未出現的資料或者缺少了第一次查詢中出現的資料(這裡並不要求兩次查詢的SQL語句相同)。這是因為在兩次查詢過程中有另外一個事務插入資料造成的。


未授權讀取ISOLATION_READ_UNCOMMITED
允許髒讀取,但不允許更新丟失。如果一個事務已經開始寫資料,則另外一個資料則不允許同時進行寫操作,但允許其他事務讀此行資料。該隔離等級可以通過“排他寫鎖”實現。
授權讀取ISOLATION_READ_COMMITTED
允許不可重複讀取,但不允許髒讀取。這可以通過“瞬間共用讀鎖”和“排他寫鎖”實現。讀取資料的事務允許其他事務繼續訪問該行資料,但是未提交的寫事務將會禁止其他事務訪問該行。 
可重複讀取ISOLATION_REPEATABLE_READ
禁止不可重複讀取和髒讀取,但是有時可能出現幻影資料。這可以通過“共用讀鎖”和“排他寫鎖”實現。讀取資料的事務將會禁止寫事務(但允許讀事務),寫事務則禁止任何其他事務。 
序列化ISOLATION_SERIALIZABLE
這個常量表示髒讀取,非重複讀取和不真實讀取都被禁止。
這個層級包括在TRANSACTION_REPEATABLE_READ阻止的事情,以及防止一個事務在滿足WHERE條件下讀所有的行記錄,第二個事務在滿足WHERE條件下插入一行,隨後前一個事務在同樣的條件下重複讀取,這是獲得的是不真實的行記錄。
ISOLATION_DEFAULT(Spring)
預設隔離等級是與具體的資料庫相關的,採取的是具體資料庫的預設隔離等級,不同的資料庫是不一樣的


事務隔離策略
Weblogic:
weblogic-ejb-jar.xml

<transaction-isolation>
   <isolation-level>TransactionSerializable</isolation-level>
   <method>
     <ejb-name>TradingService</ejb-name>
     <method-inf>Remote</method-inf>
     <method-name>placeTrade</method-name>
   </method>
</transaction-isolation>


Spring:

<bean id=“tradingService" class=“org.springframework.transaction.interceptor. TransactionProxyFactoryBean">
<property name="transactionManager"><ref bean="transactionManager"/></property>
<property name="target"><ref local=" tradingService Target"/></property>
<property name="transactionAttributes">
<props>
<prop key=“insert*">PROPAGATION_REQUIRED,ISOLATION_SERIALIZABLE</prop>
</props>
</property>
</bean>


六、事務類型本地事務模型:Local Transaction Model
程式定製事務模型:Programmatic Transaction Model
申明式事務模型:Declarative Transaction Model
七、分散式交易多個資料來源
兩段提交協議
第一步,事務控制器詢問各資源管理員是否準備好提交;
第二步,如果所有資源管理員都準備好提交,則交易管理員要求所有進行提交。

Spring交易處理
1.聲明式交易管理
2.編程式交易管理


Spring聲明式事務不提供高端應用伺服器提供的跨越遠程調用的事務上下文傳播。如果你需要這些特性,我們推薦你使用EJB。 然而,不要輕易使用這些特性。因為通常我們並不希望事務跨越遠程調用。


Spring中交易處理-申明式交易管理
事務屬性
PROPAGATION_REQUIRED
PROPAGATION_SUPPORTS
PROPAGATION_MANDATORY
PROPAGATION_REQUIRES_NEW
PROPAGATION_NOT_SUPPORTED
PROPAGATION_NEVER
PROPAGATION_NESTED如果一個活動的事務存在,則運行在一個嵌套的事務中. 如果沒有活動事務, 則按TransactionDefinition.PROPAGATION_REQUIRED 屬性執行。嵌套事務一個非常重要的概念就是內層事務依賴於外層事務。外層事務失敗時,會復原內層事務所做的動作。而內層事務操作失敗並不會引起外層事務的復原
Isolation隔離等級
read-only是否唯讀,預設為false
大多數Spring使用者選擇聲明式交易管理。這是對應用代碼影響最小的選擇,因此也最符合 非侵入式 輕量級容器的理念。
java
// the service class that we want to make transactional 
@Transactional 
public class DefaultFooService implements FooService { 
Foo getFoo(String fooName); 
Foo getFoo(String fooName, String barName); 
void insertFoo(Foo foo); 
void updateFoo(Foo foo); 
}
xml
<tx:annotation-driven transaction-manager="txManager"/> 
<!-- a PlatformTransactionManager is still required --> 
<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 
<!-- (this dependency is defined somewhere else) --> 
<property name="dataSource" ref="dataSource"/> 
</bean> 




Spring中交易處理-編程式交易管理
使用 TransactionTemplate (推薦)
直接使用一個 PlatformTransactionManager 實現


使用 TransactionTemplate
private final TransactionTemplate transactionTemplate; 
// use constructor-injection to supply the PlatformTransactionManager 
public SimpleService(PlatformTransactionManager transactionManager) { Assert.notNull(transactionManager, "The 'transactionManager' argument must not be null."); 
this.transactionTemplate = new TransactionTemplate(transactionManager); 
// the transaction settings can be set here explicitly if so desired this.transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_UNCOMMITTED); //設定交易隔離等級
this.transactionTemplate.setTimeout(30); // 事務逾時


transactionTemplate.execute(new TransactionCallbackWithoutResult() { 
protected void doInTransactionWithoutResult(TransactionStatus status) { 
try { 
   updateOperation1(); 
   updateOperation2(); 
} catch (SomeBusinessExeption ex) { 
   status.setRollbackOnly(); //復原
}

});


使用 PlatformTransactionManager 


DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 
// explicitly setting the transaction name is something that can only be done programmatically 
def.setName("SomeTxName"); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); 


TransactionStatus status = txManager.getTransaction(def); 
try { 
// execute your business logic here 
} catch (MyException ex) {
 txManager.rollback(status);
 throw ex; 

txManager.commit(status);


<bean id="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> 

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.