Spring提供两种事务管理方式,分为编程式和声明式。
- 编程式:通过编码的方式手动启用、提交或回滚事务,粒度更细,但更麻烦。
- 声明式:通过在方法或类或接口上添加注解进行包装,无侵入地实现事务,更方便,但粒度更大。
需要注意的是,使用的数据库需要支持事务,否则事务将不起作用。如MySql的MyIsam引擎就不支持事务。
2.实例 业务代码在下面的实例中,我要先创建申请,再创建申请处理。如果创建申请处理失败,应该回滚。这里是没加事务的。为了演示,我们先注掉第7行,模拟出错。
@Override public boolean saveTransaction(CertApply certApply) { certApply.setState(1); //初审中 save(certApply); ApplyDeal applyDeal = new ApplyDeal(); applyDeal.setState(1); //初审 applyDeal.setApplyId(certApply.getId()); applyDealService.save(applyDeal); return true; }运行测试
显然出现了我们要看到的问题
接下来开始使用事务进行管理
开启事务管理org.springframework spring-tx${spring.version}
@SpringBootApplication @EnableAspectJAutoProxy @EnableTransactionManagement @MapperScan("com.example.course_system.mapper") public class CourseSystemApplication { public static void main(String[] args) { SpringApplication.run(CourseSystemApplication.class, args); } }在方法上加上@Transaction注解
@Override @Transactional public boolean saveTransaction(CertApply certApply) { certApply.setState(1); //初审中 save(certApply); ApplyDeal applyDeal = new ApplyDeal(); applyDeal.setState(1); //初审 // applyDeal.setApplyId(certApply.getId()); applyDealService.save(applyDeal); return true; }测试
没有新的记录加入。结果正确!
4.SpringBoot实现声明式事务的几种方式-
基于动态代理支持@Transaction。
就是上面的那种方法。但这种方法是有局限性的。在有些情况下会失效。
- 同一个类中,方法A实现了事务,方法B中没实现事务,B中调用A。事务失效(没有经过代理类,俗称自调用问题)
- 数据库引擎不支持事务
- 没有被 Spring 管理
- 方法不是 public 的
- 异常被吃了 (高频)异常类型错误(一定要抛出RuntimeException,或者配置识别的事务类型)
-
基于AspectJ编译期织入来支持@Transactional
- 用来解决上面的方法不是public的时候动态代理失效的问题
我们可以采用“编译期织入”或“类加载期织入”的方式,在运行代码前,将我们的目标类的方法增强,无需管用“动态代理”实现时的种种限制。本文就接下来就讲下,如何使用AspectJ来实现在编译期对@Transactional注解的方法进行织入。
5.1.导包5.2.配置org.codehaus.mojo aspectj-maven-plugin1.11 org.springframework spring-aspects1.8 1.8 true compile
将@EnableTransactionManagement中的mode设置为AdviceMode.ASPECTJ(默认为AdviceMode.PROXY,也就是我们的动态代理~)
然后就可以啦。这里就不测试,用兴趣的同学可以去实验下。
6.一些补充知识 6.1Transaction注解的源码@Target({ElementType.TYPE, ElementType.METHOD}) @Retention(RetentionPolicy.RUNTIME) @Inherited @documented public @interface Transactional { @AliasFor("transactionManager") String value() default ""; @AliasFor("value") String transactionManager() default ""; Propagation propagation() default Propagation.REQUIRED; Isolation isolation() default Isolation.DEFAULT; int timeout() default TransactionDefinition.TIMEOUT_DEFAULT; boolean readOnly() default false; Class extends Throwable>[] rollbackFor() default {}; String[] rollbackForClassName() default {}; Class extends Throwable>[] noRollbackFor() default {}; String[] noRollbackForClassName() default {}; }
参考:事务传播机制 https://blog.csdn.net/qq_35493807/article/details/105756761
Class extends Throwable>[] noRollbackFor() default {}; String[] noRollbackForClassName() default {};
}
参考:事务传播机制 https://blog.csdn.net/qq_35493807/article/details/105756761
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)