@Transactional失效场景 1. 在类内部调用调用类内部@Transactional标注的方法 1.1 定义一个错误的@Transactional标注实现,设置一个内部调用面试的时候遇到过这个问题,当时一脸懵逼。现在记录一下。。。
@Service public class UserServiceImpl extends ServiceImpl1.2 测试用例implements IUserService { @Resource UserMapper userMapper; @Override public void oneTest() { oneTestNoPublic(); } @Transactional(rollbackFor = Exception.class) public void oneTestNoPublic(){ // 插入一条数据 int num = userMapper.insert(new User("小红", "青岛市", 18)); if (num > 0){ // 插入后制造一个错误 System.out.println(1 / 0); } // 再次插入一条数据 userMapper.insert(new User("小强", "烟台市", 21)); } }
@RestController @RequestMapping("/transactional") public class TransactionalTestController { @Resource IUserService userService; @GetMapping("/one") public void oneTest(){ try { userService.oneTest(); } catch (Exception e){ e.printStackTrace(); } } }1.3 运行后,控制台报错: 1.4 查看数据库,发现并没有回滚new User(“小红”, “青岛市”, 18)这条数据
2. @Transactional注解标注方法修饰符为非public 2.1 新写一个TestServiceImpl,将@Transactional注解标注方法修饰符为非public调用一个方法在类内部调用内部被@Transactional标注的事务方法,运行结果是事务不会正常开启。userMapper.insert(new User(“小红”, “青岛市”, 18)) *** 作没有进行回滚。
@Service public class TestServiceImpl { @Resource UserMapper userMapper; @Transactional(rollbackFor = Exception.class) void twoTestNoPublic(){ // 插入一条数据 int num = userMapper.insert(new User("小红", "青岛市", 18)); if (num > 0){ // 插入后制造一个错误 System.out.println(1 / 0); } // 再次插入一条数据 userMapper.insert(new User("小强", "烟台市", 21)); } }
@Service public class UserServiceImpl extends ServiceImpl2.2 测试用例implements IUserService { @Resource TwoTestServiceImpl twoTestService; @Override public void twoTest() { twoTestService.twoTestNoPublic(); } }
@RestController @RequestMapping("/transactional") public class TransactionalTestController { @Resource IUserService userService; @GetMapping("/two") public void twoTest(){ try { userService.twoTest(); } catch (Exception e){ e.printStackTrace(); } } }2.3 运行后,控制台报错: 2.4 查看数据库,发现并没有回滚new User(“小红”, “青岛市”, 18)这条数据
3. 事务方法内部捕捉了异常,且没有抛出新的异常 3.1 写一个内部捕捉异常,且不再抛出新的异常的方法以上的访问方式,导致事务没开启,因此在方法抛出异常时,userMapper.insert(new User(“小红”, “青岛市”, 18)) *** 作没有进行回滚。如果oneTestNoPublic()方法改为public的话将会正常开启事务,userMapper.insert(new User(“小红”, “青岛市”, 18)) 将会进行回滚。
@Service public class TestServiceImpl { @Resource UserMapper userMapper; @Transactional(rollbackFor = Exception.class) public void threeTestNoPublic(){ // 插入一条数据 int num = userMapper.insert(new User("小红", "青岛市", 18)); if (num > 0){ try { // 插入后制造一个错误 System.out.println(1 / 0); } catch (Exception e) { e.printStackTrace(); return; } } // 再次插入一条数据 userMapper.insert(new User("小强", "烟台市", 21)); } }3.2 测试用例
@RestController @RequestMapping("/transactional") public class TransactionalTestController { @Resource IUserService userService; @GetMapping("/three") public void threeTest(){ try { userService.threeTest(); } catch (Exception e){ e.printStackTrace(); } } }3.3 运行后,控制台报错: 3.4 查看数据库,发现并没有回滚new User(“小红”, “青岛市”, 18)这条数据
如果需要在catch里面回滚数据的话,就需要抛出新的异常或者在catch里面使用如下代码:TransactionAspectSupport.currentTransactionStatus().setRollbackonly();
好了,上面三种就是@Transactional注解不起作用,@Transactional注解失效的主要原因。
个人博客地址:http://www.zhouzhaodong.xyz/
测试代码地址为:https://gitee.com/zhouzhaodong/springboot/tree/master/transactional
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)