@Transactional失效场景

数据库引擎不支持事务

异常被catch捕获导致@Transactional失效

如果Transactional注解应用在非public 修饰的方法上,Transactional将会失效。

@Transactional 注解属性 propagation 设置错误,以下三种 propagation,事务将不会发生回滚。

TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。

TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。

TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。

@Transactional 注解属性 rollbackFor 设置错误

Spring默认在抛出了未检查unchecked异常(继承自 RuntimeException 的异常)或者 Error时才回滚事务;其他异常不会触发回滚事务。如果在事务中抛出其他类型的异常,但却期望 Spring 能够回滚事务,就需要指定 rollbackFor属性。

同一个类中方法调用,导致@Transactional失效

示例:

Service层代码

@Service
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int deleteByDeptno(Integer deptno) {
        deptMapper.deleteByPrimaryKey(deptno);
        throw new RuntimeException();//模拟出错
    }
    @Override
    public int save(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = deleteByDeptno(83); //没有使用代理,事务传播不会生效
        return res1 + res2; //模拟出错
    }
}

测试代码

@SpringBootTest
class DeptServiceImplTest {
    @Resource
    private DeptService deptService;
    @Test
    void insert() {
        Dept dept = Dept.builder()
                .dname("bb")
                .loc("bbbbbbbbb").build();
        int insert = deptService.insert(dept);
        System.out.println(insert);
    }
}

尽管deleteByDeptno()方法开启了事务,但save()方法中调用deleteByDeptno()方法进没有使用代理,所以事务传播不会生效,即出错事务不会回滚。

Service层代码

@Service
public class DeptServiceImpl implements DeptService {
    @Resource
    private DeptMapper deptMapper;
    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public int deleteByPrimaryKey(Integer deptno) {
        deptMapper.deleteByPrimaryKey(deptno);
        throw new RuntimeException();//模拟出错
    }
    @Resource
    private DeptService deptService;
    @Override
    //@Transactional(propagation = Propagation.REQUIRED)
    public int insert(Dept record) {
        int res1 = deptMapper.insert(record);//插入
        int res2 = deptService.deleteByPrimaryKey(83);//使用了代理,事务会回滚
        //System.out.println(3 / 0);
        return res1 + res2; //模拟出错
    }
}

deleteByDeptno()方法开启了事务,save()方法中调用deleteByDeptno()方法进使用了代理,所以事务传播会生效,即出错事务会回滚。

你可能感兴趣的:(#,SpringBoot,#,Spring)