首先修改applicationContext.xml如下:



[java] 
​​view plain​​​
​​​copy​​
1. …
2. <!-- 定义一个数据源 -->
3. <bean id="dataSource" class="org.apache.tomcat.jdbc.pool.DataSource">
4. "driverClassName" value="com.mysql.jdbc.Driver" />
5. "url" value="jdbc:mysql://localhost:3306/spring_test" />
6. "username" value="root" />
7. "password" value="root" />
8. </bean>
9.
10. <!-- 定义JdbcTemplate的Bean -->
11. <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"
12. "dataSource">
13. </bean>
14.
15. <!-- 配置事务管理器 -->
16. <bean id="txManager"
17. class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
18. "dataSource">
19. </bean>
20.
21. <!-- enables scanning for @Transactional annotations -->
22. <tx:annotation-driven transaction-manager="txManager" />
23.
24. <!-- 在该Bean的代码中标注@Transactional可以被事务管理器注入 -->
25. <bean id="userScore"
26. class="net.hingyi.springDemo.transaction.service.UserScoreServiceImpl"
27. "userScoreRepository_jdbc" />
28.
29. <bean id="userScoreRepository_jdbc"
30. class="net.hingyi.springDemo.transaction.repository.UserScoreRepositoryImpl"
31. "jdbcTemplate" />
32. …


 实现类代码:

[java] 
​​view plain​​​
​​​copy​​
1. @Transactional
2. public class UserScoreRepositoryImpl implements UserScoreRepository {
3.
4. private JdbcTemplate jdbcTemplate;
5.
6. @Override
7. public UserScore getUserSocore(String userNo) {
8.
9. final UserScore us = new UserScore();
10. ...
11. return us;
12. }
13. ...
14.
15. }


OK了!以上就实现了简单的事务管理了。现在再稍微了解下@Transactional。


在配置文件中,默认情况下,<tx:annotation-driven>会自动使用名称为transactionManager的事务管理器。

所以,如果定义的事务管理器名称为transactionManager,那么就可以直接使用<tx:annotation-driven/>。如下:


[java] 
​​view plain​​​
​​​copy​​
1. <!-- 配置事务管理器 -->
2. "transactionManager"
3. class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
4. "dataSource">
5. </bean>
6.
7. for @Transactional annotations -->
8. <tx:annotation-driven/>

<tx:annotation-driven>一共有四个属性如下,


  • mode:指定Spring事务管理框架创建通知bean的方式。可用的值有proxy和aspectj。前者是默认值,表示通知对象是个JDK代理;后者表示Spring AOP会使用AspectJ创建代理
  • proxy-target-class:如果为true,Spring将创建子类来代理业务类;如果为false,则使用基于接口的代理。(如果使用子类代理,需要在类路径中添加CGLib.jar类库)
  • order:如果业务类除事务切面外,还需要织入其他的切面,通过该属性可以控制事务切面在目标连接点的织入顺序。
  • transaction-manager:指定到现有的PlatformTransaction Manager bean的引用,通知会使用该引用

@Transactional标注的位置


@Transactional注解可以标注在类和方法上,也可以标注在定义的接口和接口方法上。


如果我们在接口上标注@Transactional注解,会留下这样的隐患:因为注解不能被继承,所以业务接口中标注的@Transactional注解不会被业务实现类继承。所以可能会出现不启动事务的情况。所以,Spring建议我们将@Transaction注解在实现类上。


在方法上的@Transactional注解会覆盖掉类上的@Transactional。

使用不同的事务管理器
如果我们要程序中使用多个事务管理器(主要是针对多数据源的情况),可以通过以下的方式实现:
Service代码:



[java] 
​​view plain​​​
​​​copy​​
1. public class MultiTxService {
2. @Transactional("tran_1")
3. public void addTest(int id){
4.
5. }
6. @Transactional("tran_2")
7. public void deleteTest(int id){
8.
9. }
10.
11. }


applicationContext.xml配置如下: 



[java] 
​​view plain​​​
​​​copy​​
1. <bean id="tran_1"
2. class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
3. "dataSource">
4. "tran_1"/>
5. </bean>
6. <bean id="tran_2"
7. class="org.springframework.jdbc.datasource.DataSourceTransactionManager"
8. "dataSource">
9. "tran_2"/>
10. </bean>

经过以上的代码,每个事务都会绑定各自的独立的数据源,进行各自的事务管理。我们可以优化下以上代码,可以自定义一个绑定到特定事务管理器的注解,然后直接使用这个自定义的注解进行标识:



[java] 
​​view plain​​​
​​​copy​​
1. @Target({ElementType.METHOD,ElementType.TYPE})
2. @Retention(RetentionPolicy.RUNTIME)
3. @Transactional("tran_1")
4. public @interface CustomerTransactional {
5.
6. }

在Service代码中使用:


[java] 
​​view plain​​​
​​​copy​​
1. ...
2. //使用名为tran_1的事务管理器
3. @CustomerTransactional
4. public void addTest(String str){
5.
6. }
7. …