天天看點

Spring事務Spring事務管理2、事務的屬性3 事務管理器4. Spring程式設計式管理事務5. Spring聲明式管理事務

轉載請注明出處:https://mp.csdn.net/mdeditor/83614701

Spring事務管理

Spring支援支援程式設計式和聲明式兩種事務管理。程式設計式事務管理是在業務中嵌入控制事務送出和復原的事務管理代碼來實作。通常在方法正常完成時送出事務,而在方法抛出異常是復原事務。使用程式設計式事務,你可以定義自己的事務送出和復原規則。

聲明式的事務管理的靈活性不如程式設計式,程式設計式事務管理允許你通過代碼控制事務-----顯示的在在你覺得合适的時候啟動、送出、合并事務。你可以指定一組事務的屬性,在很細的粒度上定義事務。

2、事務的屬性

  • 原子性 :事務是包含一系列操作的的原子操作,這些操作要麼全部完成,要麼全部不完成。
  • 一緻性: 一旦事務的所有操作結束,事務就被送出。然後你的資料和資源将處于遵循業務規則的的一緻性裝态。
  • 隔離性:在相同資料資料集上同時可能有多個事務處理,每個事務應該與其它事務隔離,避免資料被破換。
  • 持久性: 一旦事務完成,它的結果應該能承受任何系統錯誤(想象一下事務在送出過程中被切斷電源的情況)。通常,事務的結果被寫入持續性存儲。

2.1 jdbc管理事務

try {
	conn = datasource.getConnection;
	conn.setAutoCommit(false);
	...這裡寫操作資料庫的業務代碼...
	conn.commit();
	} catch (SQLException e ) {
		if (conn!=null) {
			try {
				conn.rollback();
			} catch (SQLException e) {}
		}
	} finally {
		if (conn!=null) {
			try {
			conn.close();
			} catch (SQLException e) {}
		}
	}
           

這種代碼是JDBC專用的,一旦你選擇其它資料通路政策,這些代碼也需要改變。Spring事務支援提供了一組技術獨立的機制,包括事務管理器、事務模闆、和事務聲明式支援以簡化你的事務管理任務。

3 事務管理器

Spring幫我們從不同的事務管理API中抽象出了一組通用的事務機制,作為開發人員你隻要利用Spring的事務機制,不需要知道太多底層的細節,你的事務管理代碼将獨立于任何特定的事務技術。

Spring的核心事務管理抽象基于PlatformTransactionManager接口,它封裝了一組用于事務管理的技術獨立代碼。不論你在Spring選擇哪一種事務管理政策(聲明式或者程式設計式)都需要事務管理器,PlatformTransactionManager提供三種處理事務的方法:

  • TranscactionStatus getTransaction(TransactionDefination definition)throws TransactionException
  • void commit(TransactionStatus status)
  • void rollback(TransactionStatus status)

3.1 事務管理器的實作

PlatformTransactionManager隻是一個接口,這個接口有多重實作。

  • 應用程式隻有一個資料源并且使用JDBC進行通路,使用DataSourceManager。
  • 如果使用orm架構通路資料庫,則選擇對應該架構的事務管理器。例如HiberateTransactionManager。
Spring事務Spring事務管理2、事務的屬性3 事務管理器4. Spring程式設計式管理事務5. Spring聲明式管理事務

PlatformTransactionManager接口常見實作圖

是以,我們在Spring的IOC容器中聲明bean就行了。class是事務管理器的具體實作,還需要設定一個dataSource屬性,以便管理這個資料源建立的連接配接。

4. Spring程式設計式管理事務

4.1 使用事務管理器程式設計式管理事務

前面說過無論是程式設計式事務管理 還是聲明式事務管理都需要spring事務管理器。spring事務管理器提供了獨立的api來管理事務。它提供了一套api

  • getTransaction() 啟動新事務或者是擷取目前活躍的事務。
  • commit()
  • rollback()

    使用事務管理器程式設計式管理事務的代碼大緻如下:

TransactionDefinition ref = new DefaultTransactionDefinition();
		TransactionStatus status = transactionManager.getTransaction(ref);
		try {
				//----這裡寫業務邏輯代碼-----
				transactionManager.commit(status);
		} catch (Exception e) {
			 T.console(e.getMessage());
//			 TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
			 transactionManager.rollback(status);
			 return null;
		}
           

TransactionDefinition 對象用于指定事務屬性,DefaultTransactionDefinition是它的一個實作,使用預設的屬性。

4.2 使用事務模闆程式設計式管理事務

如果你一直使用Spring事務管理器程式設計式管理事務,你看你會覺得厭煩,因為你一直在寫重複的代碼。是以,和JDBC模闆一樣,Spring提供了TransactionTemplate幫助你管理事務。你隻需要在一個實作了TransactionCallback接口的回調類裡封裝你的業務代碼,并将其傳遞給TransactionTemplate的execute方法執行就可以了

代碼大緻如下:

TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
		transactionTemplate.execute(new TransactionCallback<T>() {
			
			@Override
			public T doInTransaction(TransactionStatus status) {
//				這裡寫你的業務邏輯
				return null;
			}
		});
           

這種方法的好處在于不需要負責啟動、復原、或者送出事務。

在回調對象執行期間,如果抛出了一個非受控異常(例如:RuntimeException、DataAccessException),事務将會復原,否則事務将在回調對象完成後送出。

建議不要向上面代碼一樣直接new 事務模闆,最好交給Spring容器建立,事務模闆依賴于事務管理器,相應的xml配置不做說明了。注意:事務模闆執行個體是可以用于超過一個事務性的Bean的。因為它是一個線程安全對象,這也是為什麼能放在容器中的原因了(spring建立的對象預設是單例的哦~)。

5. Spring聲明式管理事務

因為事務管理是橫切關注點,應該使用Spring聲明式的管理事務。

5.1 使用事務通知聲明式的管理事務

為了啟用聲明式的事務管理,你可以通過tx schema中定義的 tx:advice 聲明一個事務通知,這樣你必須要先添加schema限制。

如果你聲明了這個通知,就必須将其與一個連接配接點相關聯。因為事務通知在 <aop: config>元素之外聲明,它不能與連接配接點直接連結,你必須在在<aop:config>元素中聲明一個通知器(Advisor),将通知與切入點關聯。

因為SpringAOP使用AspectJ切入點表達式定義切入點,是以必須添加AspectJ織入支援。

<dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjweaver</artifactId>
            <version>1.7.1</version>
        </dependency>
           

添加schame限制

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:jee="http://www.springframework.org/schema/jee"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:c="http://www.springframework.org/schema/c"
	xmlns:task="http://www.springframework.org/schema/task"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
	<!--  ....... -->
</beans>
           
<!-- 配置通知 -->
	<tx:advice id="xxxTransactionAdvice">
		<!-- 指定需要事務管理的方法 -->
		<tx:attributes>
		<!-- 比對到類下方法的切入點 sava* 表示比對所有以sava開頭 的方法  -->
		<!-- 這裡還可以配置事務定義 :傳播行為  隔離級别  逾時時間 是否隻讀  這裡不配置全部使用預設的-->
			<tx:method name="save*"/>
		</tx:attributes>
	</tx:advice>	

		
	<aop:config>
		<!-- 表示在所有切入點加事務管理 -->
		<aop:pointcut expression="execution(* cn.pconline.activity.service.AwardService.*(..))" id="awardPointcut"/>
		<aop:advisor advice-ref="xxxTransactionAdvice" pointcut-ref="awardPointcut"/>
	</aop:config>
           

Spring AOP基于代理,它隻能應用到公開方法,是以隻有公共方法才能用Spring AOP聲明為事務性的。

每個事務通知都需要聲明一個事務管理器,如果你沒有聲明,Spring會在上下文中尋找一個bean名稱為transactionManager的元件。

一切準備妥當 ,現在你可以從容器中擷取AwardService的執行個體對象,這個bean的方法比對該切入點,Spring将傳回一個代理,為這個bean啟動事務管理。

5.2 使用@Transactional注解聲明式的管理事務。

在bean配置檔案中聲明事務用到AOP的相關知識,對于初學者來說,比較費勁。

是以,Spring允許通過@Transactional注解你的事務性方法,并且啟用<tx:annotation-driven>元素聲明注解。

由于SpringAOP基于代理的局限性,你應該隻注解public 方法。

@Transactional注解可以用在類上,添加到類上時候,表示該類中所有的public方法将定義為事務性的

使用說明:

  • 在bean配置檔案中聲明中 ,開啟注解支援的事務tx:annotation-driven 并為它注冊一個事務管理器。
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:task="http://www.springframework.org/schema/task"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.2.xsd
		http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
   <!-- 開啟注解支援事務的功能 --> 
    <!-- 如果你未聲明該屬性,spring将在ioc容器中自動查找名為transactionManager的元件 -->
    <tx:annotation-driven transaction-manager="transactionManager"/>
    <!-- 事務管理器 -->
 <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager" p:dataSource-ref="dataSource"/>
</beans>
           

Spring事務的使用方式就先介紹到這裡,下一篇再詳細介紹Spring事務的屬性。