spring事务的开启方式(编程式和声明式)

2021-06-26 23:05

阅读:488

 1 事务管理器配置
 2 class="com.mchange.v2.c3p0.ComboPooledDataSource">
 3      4      5      6      7       
 8       9          510      11       
12      13          3014      15       
16      17          1018      19       
20      21          6022      23       
24      25          526      27       
28      29          030      31       
32      33          6034      35       
36      37          3038      39       
40      41          true42      43       
44      45          false46      47 48 
49 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
50     51 
 1 业务中使用代码(以测试类展示)
 2 import java.util.Map;
 3 import javax.annotation.Resource;
 4 import javax.sql.DataSource;
 5 import org.apache.log4j.Logger;
 6 import org.junit.Test;
 7 import org.junit.runner.RunWith;
 8 import org.springframework.jdbc.core.JdbcTemplate;
 9 import org.springframework.test.context.ContextConfiguration;
10 import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
11 import org.springframework.transaction.PlatformTransactionManager;
12 import org.springframework.transaction.TransactionDefinition;
13 import org.springframework.transaction.TransactionStatus;
14 import org.springframework.transaction.support.DefaultTransactionDefinition;
15  
16 @RunWith(SpringJUnit4ClassRunner.class)
17 @ContextConfiguration(locations = { "classpath:spring-public.xml" })
18 public class test {
19     @Resource
20     private PlatformTransactionManager txManager;
21     @Resource
22     private  DataSource dataSource;
23     private static JdbcTemplate jdbcTemplate;
24     Logger logger=Logger.getLogger(test.class);
25     private static final String INSERT_SQL = "insert into testtranstation(sd) values(?)";
26     private static final String COUNT_SQL = "select count(*) from testtranstation";
27     @Test
28     public void testdelivery(){
29         //定义事务隔离级别,传播行为,
30         DefaultTransactionDefinition def = new DefaultTransactionDefinition();  
31         def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
32         def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);  
33         //事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
34         TransactionStatus status = txManager.getTransaction(def);  
35         jdbcTemplate = new JdbcTemplate(dataSource);
36         int i = jdbcTemplate.queryForInt(COUNT_SQL);  
37         System.out.println("表中记录总数:"+i);
38         try {  
39             jdbcTemplate.update(INSERT_SQL, "1");  
40             txManager.commit(status);  //提交status中绑定的事务
41         } catch (RuntimeException e) {  
42             txManager.rollback(status);  //回滚
43         }  
44         i = jdbcTemplate.queryForInt(COUNT_SQL);  
45         System.out.println("表中记录总数:"+i);
46     }
47     
48 }

2)使用TransactionTemplate,该类继承了接口DefaultTransactionDefinition,用于简化事务管理,事务管理由模板类定义,主要是通过TransactionCallback回调接口或TransactionCallbackWithoutResult回调接口指定,通过调用模板类的参数类型为TransactionCallback或TransactionCallbackWithoutResult的execute方法来自动享受事务管理。

TransactionTemplate模板类使用的回调接口:

  • TransactionCallback:通过实现该接口的“T doInTransaction(TransactionStatus status) ”方法来定义需要事务管理的操作代码;
  • TransactionCallbackWithoutResult:继承TransactionCallback接口,提供“void doInTransactionWithoutResult(TransactionStatus status)”便利接口用于方便那些不需要返回值的事务操作代码。

还是以测试类方式展示如何实现

 1 @Test
 2 public void testTransactionTemplate(){
 3     jdbcTemplate = new JdbcTemplate(dataSource);
 4     int i = jdbcTemplate.queryForInt(COUNT_SQL);  
 5     System.out.println("表中记录总数:"+i);
 6     //构造函数初始化TransactionTemplate
 7     TransactionTemplate template = new TransactionTemplate(txManager);
 8     template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
 9     //重写execute方法实现事务管理
10     template.execute(new TransactionCallbackWithoutResult() {
11         @Override
12         protected void doInTransactionWithoutResult(TransactionStatus status) {
13             jdbcTemplate.update(INSERT_SQL, "饿死");   //字段sd为int型,所以插入肯定失败报异常,自动回滚,代表TransactionTemplate自动管理事务
14         }}
15     );
16     i = jdbcTemplate.queryForInt(COUNT_SQL);  
17     System.out.println("表中记录总数:"+i);
18 }

2.声明式事务:可知编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的,而声明式事务不同,声明式事务属于无侵入式,不会影响业务逻辑的实现。

声明式事务实现方式主要有2种,一种为通过使用Spring的定义事务通知与AOP相关配置实现,另为一种通过@Transactional实现事务管理实现,下面详细说明2种方法如何配置,已经相关注意点
1)方式一,配置文件如下
 1 
12 13     14         
15         for="" rollback-for=""/>
16         
17         18     19 20 
21 
22     
23     
24     
25 
关于事务传播行为与隔离级别,可参考http://blog.csdn.net/liaohaojian/article/details/68488150
注意点:
  1. 事务回滚异常只能为RuntimeException异常,而Checked Exception异常不回滚,捕获异常不抛出也不会回滚,但可以强制事务回滚:TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
  2. 解决“自我调用”而导致的不能设置正确的事务属性问题,可参考http://www.iteye.com/topic/1122740
2)方式二通过@Transactional实现事务管理
1 class="org.springframework.jdbc.datasource.DataSourceTransactionManager">   
2      3 4 //开启事务注解
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED),具体参数跟上面中一样
Spring提供的@Transaction注解事务管理,内部同样是利用环绕通知TransactionInterceptor实现事务的开启及关闭。
使用@Transactional注意点:
    1. 如果在接口、实现类或方法上都指定了@Transactional 注解,则优先级顺序为方法>实现类>接口;
    2. 建议只在实现类或实现类的方法上使用@Transactional,而不要在接口上使用,这是因为如果使用JDK代理机制(基于接口的代理)是没问题;而使用使用CGLIB代理(继承)机制时就会遇到问题,因为其使用基于类的代理而不是接口,这是因为接口上的@Transactional注解是“不能继承的”;


评论


亲,登录后才可以留言!