Spring事务失效的各种场景( 三 )


十二、嵌套事务回滚过头@Servicepublic class DemoService {@Autowiredprivate DemoTwoService demoTwoService;@Autowiredprivate DemoDao demoDao;public@Transactional(rollbackFor = Exception.class)publicvoid query(Demo demo) throws Exception{demoDao.save(demo);demoTwoService.save(demo);}}原本只是希望回滚demoServise.save(),不回滚demoDao.save(demo);,但是这种情况两个都会被回滚,因为demoTwoService.save(demo);没有捕获异常,往上抛出,导致query进行回滚,所以同时回滚了两个
解决方法:
@Servicepublic class DemoService {@Autowiredprivate DemoTwoService demoTwoService;@Autowiredprivate DemoDao demoDao;public@Transactional(rollbackFor = Exception.class)publicvoid query(Demo demo) throws Exception{demoDao.save(demo);try {demoTwoService.save(demo);} finally {}}}可以将内部嵌套事务放在try/catch中,并且不继续往上抛异常 。这样就能保证,如果内部嵌套事务中出现异常,只回滚内部事务,而不影响外部事务 。
十三、编程式事务上面的事务失效都是基于@Transactional注解的,我们把这种事务叫做:声明式事务 。
其实,spring还提供了另外一种创建事务的方式,即通过手动编写代码实现的事务,我们把这种事务叫做:编程式事务 。
@Servicepublic class DemoService {@Autowiredprivate TransactionTemplate transactionTemplate;@Transactional(rollbackFor = Exception.class)publicvoid query(Demo demo) throws Exception{transactionTemplate.execute((status -> {save(demo);return Boolean.TRUE;}));}@Transactionalpublic void save(Demo demo) {}}在spring中为了支持编程式事务,专门提供了一个类:TransactionTemplate,在它的execute方法中,就实现了事务的功能 。
【Spring事务失效的各种场景】使用TransactionTemplate的编程式事务可以
• 避免由于spring aop问题,导致事务失效的问题 。
• 能够更小粒度的控制事务的范围 。
tips:关于本文举例的query加事务不太符合开发的要求,但是有点懒就不改了




推荐阅读