spring事务的开启方式(编程式和声明式)
2021-06-26 23:05
阅读:488
1 事务管理器配置 2class="com.mchange.v2.c3p0.ComboPooledDataSource"> 3 48 494 5 6 7 8 9 11 125 1013 15 1630 1417 19 2010 1821 23 2460 2225 27 285 2629 31 320 3033 35 3660 3437 39 4030 3841 43 44true 4245 47false 46class="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 1213 20 21 22 23 24 2514 15 19for="" rollback-for=""/> 16 17 18
关于事务传播行为与隔离级别,可参考http://blog.csdn.net/liaohaojian/article/details/68488150
注意点:
- 事务回滚异常只能为RuntimeException异常,而Checked Exception异常不回滚,捕获异常不抛出也不会回滚,但可以强制事务回滚:TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
- 解决“自我调用”而导致的不能设置正确的事务属性问题,可参考http://www.iteye.com/topic/1122740
1class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 2 43 //开启事务注解
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED),具体参数跟上面中一样
Spring提供的@Transaction注解事务管理,内部同样是利用环绕通知TransactionInterceptor实现事务的开启及关闭。
使用@Transactional注意点:
使用@Transactional注意点:
- 如果在接口、实现类或方法上都指定了@Transactional 注解,则优先级顺序为方法>实现类>接口;
- 建议只在实现类或实现类的方法上使用@Transactional,而不要在接口上使用,这是因为如果使用JDK代理机制(基于接口的代理)是没问题;而使用使用CGLIB代理(继承)机制时就会遇到问题,因为其使用基于类的代理而不是接口,这是因为接口上的@Transactional注解是“不能继承的”;
评论
亲,登录后才可以留言!