spring事务失效及回滚失效的各种场景

一、事务不生效(常见)

1.方法修饰符不是public

2.方法用final修饰

3.同一个类中调用事务方法,例如

@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

  
    public void add(UserModel userModel) {
        userMapper.insertUser(userModel);
        // 调用事务方法,事务不生效 
        updateStatus(userModel);
    }


    // 事务方法
    @Transactional
    public void updateStatus(UserModel userModel) {
        doSameThing();
    }
}

4.类本身未注入spring,未被spring管理

5.多线程调用

6.存储引擎不支持事务

7.未开启事务,注意:

如果你使用的是springboot当然是不需要考虑事务未开启问题

但是如果你使用的还是传统的spring项目,就需要在applicationContext.xml文件中,手动配置事务相关参数 ,  如果忘了配置,事务是不会生效的。

二、事务不回滚

1.错误的事务传播特性

我们在使用@Transactional注解时,是可以指定propagation参数的。

该参数的作用是指定事务的传播特性,spring目前支持7种传播特性:

REQUIRED 如果当前上下文中存在事务,那么加入该事务,如果不存在事务,创建一个事务。-----默认传播特性
SUPPORTS 如果当前上下文存在事务,则支持事务加入事务,如果不存在事务,则使用非事务的方式执行。
MANDATORY 如果当前上下文中存在事务,否则抛出异常。
REQUIRES_NEW 每次都会新建一个事务,并且同时将上下文中的事务挂起,执行当前新建事务完成以后,上下文事务恢复再执行。
NOT_SUPPORTED 如果当前上下文中存在事务,则挂起当前事务,然后新的方法在没有事务的环境中执行。
NEVER 如果当前上下文中存在事务,则抛出异常,否则在无事务环境上执行代码。
NESTED 如果当前上下文中存在事务,则嵌套事务执行,如果不存在事务,则新建事务。

@Service
public class UserService {
    // 事务传播特性
    @Transactional(propagation = Propagation.NEVER)
    public void add(UserModel userModel) {
        saveData(userModel);
        updateData(userModel);
    }
}

2.try...catch,异常被自己处理掉了,不会触发回滚

3.手动抛出了异常

4.自定义了回滚异常

在使用@Transactional注解声明事务时,有时我们想自定义回滚的异常,spring也是支持的。可以通过设置rollbackFor参数,来完成这个功能,  如果自定义的异常类型未能包含方法中的异常场景,  会导致不会回滚!

 @Transactional(rollbackFor = BusinessException.class)

5.嵌套异常处理(不属于不回滚的情况,了解即可)

public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleService roleService;


    // 此方法添加了事务管理机制
    @Transactional
    public void add(UserModel userModel) throws Exception {
        userMapper.insertUser(userModel);
        // 此处调用的方法本身也添加了事务管理
        // 如果dootherThing方法异常,则doOtherThing回滚,add方法也会回滚
        roleService.doOtherThing();
    }
}

@Service
public class RoleService {

    @Transactional(propagation = Propagation.NESTED)
    public void doOtherThing() {
        System.out.println("保存role表数据");
    }
}

而以上代码中,有时只需要回滚部分代码,不需要回滚的部分使用try..catch抓取异常即可,例如

@Slf4j
@Service
public class UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleService roleService;

    @Transactional
    public void add(UserModel userModel) throws Exception {

        userMapper.insertUser(userModel);
        try {
            roleService.doOtherThing();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
    }
}

  • 8
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值