Spring3事務管理——使用@Transactional 註解

先讓咱們看代碼吧!
如下代碼爲在「Spring3事務管理——基於tx/aop命名空間的配置」基礎上修改。首先修改applicationContext.xml以下:
java

…
<!-- 定義一個數據源 -->
<bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver" />
        <property name="url" value="jdbc:mysql://localhost:3306/spring_test" />
        <property name="username" value="root" />
        <property name="password" value="root" />
</bean>

<!-- 定義JdbcTemplate的Bean -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
        p:dataSource-ref="dataSource">
</bean>

<!-- 配置事務管理器 -->
<bean id="txManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
        p:dataSource-ref="dataSource">
</bean>

<!-- enables scanning for @Transactional annotations -->
<tx:annotation-driven transaction-manager="txManager" />

<!-- 在該Bean的代碼中標註@Transactional能夠被事務管理器注入 -->
<bean id="userScore"
        class="net.hingyi.springDemo.transaction.service.UserScoreServiceImpl"
        p:userScoreRepository-ref="userScoreRepository_jdbc" />

<bean id="userScoreRepository_jdbc"
        class="net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl"
        p:jdbcTemplate-ref="jdbcTemplate" />
…

 實現類代碼: mysql

@Transactional
public class UserScoreRepositoryImpl implements UserScoreRepository {

	private JdbcTemplate jdbcTemplate;

	@Override
	public UserScore getUserSocore(String userNo) {

	final UserScore us = new UserScore();
	...
	return us;
	}
	...

}

OK了!以上就實現了簡單的事務管理了。如今再稍微瞭解下@Transactional。
在配置文件中,默認狀況下,<tx:annotation-driven>會自動使用名稱爲transactionManager的事務管理器。因此,若是定義的事務管理器名稱爲transactionManager,那麼就能夠直接使用<tx:annotation-driven/>。以下: spring

<!-- 配置事務管理器 -->
	<bean id="transactionManager"
		class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
		p:dataSource-ref="dataSource">
	</bean>

	<!-- enables scanning for @Transactional annotations -->
	<tx:annotation-driven/>

<tx:annotation-driven>一共有四個屬性以下, sql

  • mode:指定Spring事務管理框架建立通知bean的方式。可用的值有proxy和aspectj。前者是默認值,表示通知對象是個JDK代理;後者表示Spring AOP會使用AspectJ建立代理
  • proxy-target-class:若是爲true,Spring將建立子類來代理業務類;若是爲false,則使用基於接口的代理。(若是使用子類代理,須要在類路徑中添加CGLib.jar類庫)
  • order:若是業務類除事務切面外,還須要織入其餘的切面,經過該屬性能夠控制事務切面在目標鏈接點的織入順序。
  • transaction-manager:指定到現有的PlatformTransaction Manager bean的引用,通知會使用該引用

 @Transactional的屬性
apache

屬性名 tomcat

類型 app

說明 框架

isolation ide

枚舉org.springframework.transaction.annotation.Isolation的值 優化

事務隔離級別

noRollbackFor

Class<? extends Throwable>[]

一組異常類,遇到時不回滾。默認爲{}

noRollbackForClassName

Stirng[]

一組異常類名,遇到時不回滾,默認爲{}

propagation

枚舉org.springframework.transaction.annotation.Propagation的值

事務傳播行爲

readOnly

boolean

事務讀寫性

rollbackFor

Class<? extends Throwable>[]

一組異常類,遇到時回滾

rollbackForClassName

Stirng[]

一組異常類名,遇到時回滾

timeout

int

超時時間,以秒爲單位

value

String

可選的限定描述符,指定使用的事務管理器

@Transactional標註的位置
@Transactional註解能夠標註在類和方法上,也能夠標註在定義的接口和接口方法上。
若是咱們在接口上標註@Transactional註解,會留下這樣的隱患:由於註解不能被繼承,因此業務接口中標註的@Transactional註解不會被業務實現類繼承。因此可能會出現不啓動事務的狀況。因此,Spring建議咱們將@Transaction註解在實現類上。
在方法上的@Transactional註解會覆蓋掉類上的@Transactional。

使用不一樣的事務管理器
若是咱們要程序中使用多個事務管理器(主要是針對多數據源的狀況),能夠經過如下的方式實現:
Service代碼:

public class MultiTxService {
	@Transactional("tran_1")
	public void addTest(int id){
		
	}
	@Transactional("tran_2")
	public void deleteTest(int id){
		
	}

}

applicationContext.xml配置以下: 

<bean id="tran_1"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
	p:dataSource-ref="dataSource">
	<qualifier value="tran_1"/>
</bean>
<bean id="tran_2"
	class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
	p:dataSource-ref="dataSource">
	<qualifier value="tran_2"/>
</bean>

通過以上的代碼,每一個事務都會綁定各自的獨立的數據源,進行各自的事務管理。咱們能夠優化下以上代碼,能夠自定義一個綁定到特定事務管理器的註解,而後直接使用這個自定義的註解進行標識:


@Target({ElementType.METHOD,ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Transactional("tran_1")
public @interface CustomerTransactional {

}

在Service代碼中使用:

...
//使用名爲tran_1的事務管理器
@CustomerTransactional
public void addTest(String str){
	
}
…
相關文章
相關標籤/搜索