被忽略的Spring3小改进—支持多数据源的@Transactional事务注解

转载自 http://blog.csdn.net/changqing5818/article/details/58639407

问题描述

有个项目在配置Spring事务时,使用了@Transactional注解,但这个项目使用了多个数据源,而事务注解只对第一个起作用,咋办?

探幽

先回顾一下之前个人习惯使用的 + 配置方式,大致步骤如下:

1)定义与事务管理器对应的事务通知 
2)配置需要拦截的方法调用切面 
3)将切入点连接到相应的事务通知
整个系统的事务,三下配置,一处搞定,相比注解方式,个人觉得更简单、省力、统一。

但是在spring2.5以前,对分布式多数据源不支持,但是在spring3.0之后针对这个问题的,新增了一节(10.5.6.2)来解决,参见:(http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction-declarative-annotations

Most Spring applications only need a single transaction manager, but there may be situations where you want multiple independent transaction managers in a single application. The value attribute of the @Transactional annotation can be used to optionally specify the identity of the PlatformTransactionManager to be used. This can either be the bean name or the qualifier value of the transaction manager bean。

大致意思是在Spring2.5之前,@Transactional注解确实不支持多数据源,但是Spring3为其增加了value属性配置,可以指定当前事务通知对应的事务管理器。

检查了一下Spring的changelogs,这个特性是在3.0M4版中加入的:

@Transactional supports qualifier value for choosing between multiple transaction managers

解决办法

1、配置事务注解驱动、每个数据源对应的事务管理器,并定义“限定符”

<!-- 开启注解式事务扫描 -->
<tx:annotation-driven/>

  <bean id="transactionManager1" class="org.springframework.jdbc.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource1">
    <qualifier value="order"/>
  </bean>

  <bean id="transactionManager2" class="org.springframework.jdbc.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource2">
    <qualifier value="account"/>
  </bean>

2、在需要事务的地方,指定“限定符”

public class TransactionalService {

    @Transactional("order")
    public void setSomething(String name) { ... }

    @Transactional("account")
    public void doSomething() { ... }
  }

3、如果不指定“限定符”,将默认使用“transationManager”命名对应的事务管理器

The default <tx:annotation-driven> target bean name transactionManager will still be used if no specifically qualified PlatformTransactionManager bean is found.

在配置文件中,默认情况下,会自动使用名称为transactionManager的事务管理器。所以,如果定义的事务管理器名称为transactionManager,那么就可以直接使用

@Transactional的属性

这里写图片描述

配置优化

可以自定义一个绑定到特定事务管理器的注解,然后直接使用这个自定义的注解进行标识:

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

}

在Service代码中使用:

//使用名为tran_1的事务管理器
@CustomerTransactional
public void addTest(String str){

}

猜你喜欢

转载自blog.csdn.net/fgyibupi/article/details/78047418
今日推荐