美文网首页程序员
Spring事务失效不回滚的几种案列

Spring事务失效不回滚的几种案列

作者: 风静花犹落 | 来源:发表于2022-03-25 18:17 被阅读0次

简介

Spring使用AOP代理实现事务,默认情况下只捕获 RuntimeException 的异常

概况

  1. 抛出非RuntimeException
  2. 若异常被捕获且不抛出,则不会回滚
  3. 不经Spring代理,直接调用本类方法
  4. 未正确使用事物的propagation(传播)属性
  5. 方法被staticfinal非public方法修饰
  6. 业务类没有托管给Spring注册为Bean对象
  7. 切面的优先级在事物之前,需手动回滚异常
  8. 数据库使用了不支持事务的存储引擎,如:Mysql中的MyISAM
  9. 在多线程场景中,获取到的数据库连接是不一样的,即是不属于同一事务,则无法回滚
  10. 需要调用的业务类,在事物被声明之前注册成Bean对象,即优先级高于事物,导致事物失效

案列一

问题详情

一、抛出非RuntimeException

public void saveUser(User user) {
    try {
        userDao.save(user);
    } catch (Exception e) {
        //抛出非RuntimeException
        throw new IllegalAccessException();
    }
}

解决方案

一、申明回滚异常

//通过注解rollbackFor,申明回滚的异常
@Transactional(rollbackFor = Exception.class)
public void saveUser(User user) {
    try {
        userDao.save(user);
    } catch (Exception e) {
        throw new IllegalAccessException();
    }
}

案列二

问题详情

一、若异常被捕获且不抛出,则不会回滚

public void saveUser(User user) {
    try {
        userDao.save(user);
    } catch (Exception e) {
        logger.info("保存失败:错误信息为:" + e);
    }
}

解决方案

一、显式抛出异常

public void saveUser(User user) {
    try {
        userDao.save(user);
    } catch (Exception e) {
        logger.info("保存失败:错误信息为:" + e);
        //显式抛出异常
        throw new RuntimeException();
    }
}

二、手动回滚事物

public void saveUser(User user) {
    
    try {
        userDao.save(user);
    } catch (Exception e) {
        logger.info("保存失败:错误信息为:" + e);
        //手动回滚事物
        TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
    }
    
} 

案列三

问题详情

一、不经Spring代理,直接调用本类方法

@Service
public class UserServiceImpl implements UserService {
        
    public boolean saveUser(User user) {
        //不经Spring代理,直接调用本类方法
        return this.save(user);
    }
    
    @Transactional(rollbackFor = Exception.class)
    public boolean save(User user) {
        return userDao.save(user);
    }

}

解决方案

一、使用AspectJ 代理

1. 在启动类上开启代理

@SpringBootApplication
//启用AspectJ 代理
@EnableAspectJAutoProxy(exposeProxy = true, proxyTargetClass = true)
public class UserApplication {

    public static void main(String[] args) {
        SpringApplication.run(UserApplication.class, args);
    }

}

2. 使用代理调用本地方法

@Service
public class UserServiceImpl implements UserService {
    
    public boolean saveUser(User user) {
        //使用AspectJ 代理
        return ((UserService) (AopContext.currentProxy())).save(user);
    }

    
    @Transactional(rollbackFor = Exception.class)
    public boolean save(User user) {
        return userDao.save(user);
    }

    
}    

案列四

问题详情

一、未正确使用事物的propagation(传播)属性

@Transactional(propagation = Propagation.NOT_SUPPORTED)

解决方案

一、使用默认propagation(传播)属性

@Transactional(propagation = Propagation.REQUIRED)

案列八

JPA配置InnoDB存储引擎

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect

相关文章

  • Spring事务失效不回滚的几种案列

    简介 Spring使用AOP代理实现事务,默认情况下只捕获 RuntimeException 的异常 概况 抛出非...

  • SpringBoot事务回滚问题

    SpringBoot事务不回滚问题 Spring声明式事务管理默认对 非检查型异常 或 运行时异常 进行事务回滚,...

  • Spring事务

    先说结论:Spring事务异常回滚,捕获异常不抛出就不会回滚。最近遇到了事务不回滚的情况,我还考虑说JPA的事务有...

  • 事务相关的问题总结

    一、事务回滚问题 二、事务失效问题 三、事务失效的解决办法 方式一:自己手动创建事务,提交事务,回滚事务(Spri...

  • SpringBoot 事务回滚问题排查

    公司遇到一个问题,同样的代码不同机器打包出现事务回滚和不回滚,而每次本地调试事务均能生效。 spring事务配置 ...

  • Spring声明式事务为何不回滚---探究

    1.spring事务不回滚的两个原因 总结一下导致事务不回滚的两个原因:一是Service类内部方法调用,二是tr...

  • Spring事务失效的几种原因

    数据库引擎不支持事务 在MySQL数据库中有几种引擎(InnoDB,MyISAM,Memory等等),仅仅Inno...

  • Spring学习笔记(五)-事务的管理

    1.Spring的事务提交回滚 (1).运行期抛出的异常,spring会将事务回滚也就是(uncheck的异常) ...

  • 二十、spring事务之回滚事务

    Spring事务信息准备好后,如果我们的程序出现了异常,又会如何回滚事务呢?这节我们分析Spring事务回滚原理。...

  • Spring事务什么时候会失效

    Spring事务什么时候会失效? Spring事务的原理是AOP,进行了切面增强,那么失效的根本原因是这个AOP不...

网友评论

    本文标题:Spring事务失效不回滚的几种案列

    本文链接:https://www.haomeiwen.com/subject/tgedjrtx.html