Spring事务管理实现方式之编程式事务与声明式事务详解

本文内容纲要:Spring事务管理实现方式之编程式事务与声明式事务详解

转载自:http://blog.csdn.net/liaohaojian/article/details/70139151

1、简介:

通俗的来说,编程式事务需要自己写代码管理事务【自己写try...catch,自己写代码来控制事务的提交和回滚机制】;声明式事务是通过spring来管理事务的提交和回滚,无需自己写代码。

编程式事务每次实现都要单独实现,当业务量大功能复杂时无疑是繁琐痛苦的。声明式事务实现方式主要有2种,一种为通过使用Spring的tx:advice定义事务通知与AOP相关配置实现,另为一种通过@Transactional注解实现事务管理【我们做的ODS项目用的是就是@Transactional注解的形式管理事务】。

2.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理)

Spring实现编程式事务,依赖于2大类,分别是上篇文章提到的PlatformTransactionManager,与模版类TransactionTemplate(推荐使用)。下面分别详细介绍Spring是如何通过该类实现事务管理。

1)PlatformTransactionManager,上篇文章已经详情解说了该类所拥有的方法,不记得可以回看上篇文章。

事务管理器配置

[java] view plaincopy

  1. 5
  2. 30
  3. 10
  4. 60
  5. 5
  6. 0
  7. 60
  8. 30
  9. true
  10. false

业务中使用代码(以测试类展示)

[java] view plaincopy

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

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

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

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

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

[java] view plaincopy

  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. }

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

声明式事务实现方式主要有2种,一种为通过使用Spring的tx:advice定义事务通知与AOP相关配置实现,另为一种通过@Transactional实现事务管理实现,下面详细说明2种方法如何配置,已经相关注意点

1)方式一,配置文件如下

[java] view plaincopy

  1. <tx:method name="save*" propagation="REQUIRED" isolation="READ_COMMITTED" timeout="" read-only="false" no-rollback-for="" rollback-for=""/>
  2. <tx:method name="*" propagation="SUPPORTS"/>
  3. </tx:attributes>
  4. </tx:advice>
  5. aop:config
  6. <aop:pointcut expression="execution(* com.kaizhi.*.service.impl.*.*(..))" id="pointcut"/>
  7. <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/>
  8. </aop:config>

关于事务传播行为与隔离级别,可参考http://blog.csdn.net/liaohaojian/article/details/68488150

注意点:

  1. 事务回滚异常只能为RuntimeException异常,而Checked Exception异常不回滚,捕获异常不抛出也不会回滚,但可以强制事务回滚:TransactionAspectSupport.currentTransactionStatus().isRollbackOnly();
  2. 解决“自我调用”而导致的不能设置正确的事务属性问题,可参考http://www.iteye.com/topic/1122740

2)方式二通过@Transactional实现事务管理

[java] view plaincopy

  1. <tx:annotation-driven transaction-manager="txManager"/> //开启事务注解

@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.READ_COMMITTED),具体参数跟上面tx:method中一样

Spring提供的@Transaction注解事务管理,内部同样是利用环绕通知TransactionInterceptor实现事务的开启及关闭。

使用@Transactional注意点:

  1. 如果在接口、实现类或方法上都指定了@Transactional 注解,则优先级顺序为方法>实现类>接口;

    建议只在实现类或实现类的方法上使用@Transactional,而不要在接口上使用,这是因为如果使用JDK代理机制(基于接口的代理)是没问题;而使用使用CGLIB代理(继承)机制时就会遇到问题,因为其使用基于类的代理而不是接口,这是因为接口上的@Transactional注解是“不能继承的”;

本文内容总结:Spring事务管理实现方式之编程式事务与声明式事务详解

原文链接:https://www.cnblogs.com/lyftest/p/7767966.html

以上是 Spring事务管理实现方式之编程式事务与声明式事务详解 的全部内容, 来源链接: utcz.com/z/362799.html

回到顶部