VIP免费

@Transactional注解不起作用解决办法及原理分析

事务失效
24
DEMO程序园
积分:0

简介:

Transactional失效场景介绍第一种 Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。例如以下代码。 定义一个错误的@Transactional标注实现,修饰一个默认访问符的方法/** *@authorzhoujy *@date2018年12月06日 **/ @Component publicclassTestSe

Transactional失效场景介绍

第一种

Transactional注解标注方法修饰符为非public时,@Transactional注解将会不起作用。例如以下代码。

定义一个错误的@Transactional标注实现,修饰一个默认访问符的方法

/**
* @author zhoujy
* @date 2018年12月06日
**/
@Component
public class TestServiceImpl {
   @Resource
   TestMapper testMapper;
   
   @Transactional
   void insertTestWrongModifier() {
       int re = testMapper.insert(new Test(10,20,30));
       if (re > 0) {
           throw new NeedToInterceptException("need intercept");
       }
       testMapper.insert(new Test(210,20,30));
   }

}

在同一个包内,新建调用对象,进行访问。

@Component
public class InvokcationService {
   @Resource
   private TestServiceImpl testService;
   public void invokeInsertTestWrongModifier(){
       //调用@Transactional标注的默认访问符方法
       testService.insertTestWrongModifier();
   }
}

测试用例

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {
  @Resource
  InvokcationService invokcationService;

  @Test
  public void  testInvoke(){
     invokcationService.invokeInsertTestWrongModifier();
  }
}

以上的访问方式,导致事务没开启,因此在方法抛出异常时,testMapper.insert(new Test(10,20,30));操作不会进行回滚。如果TestServiceImpl#insertTestWrongModifier方法改为public的话将会正常开启事务,testMapper.insert(new Test(10,20,30));将会进行回滚。

第二种

在类内部调用调用类内部@Transactional标注的方法。这种情况下也会导致事务不开启。示例代码如下。

设置一个内部调用

/**
* @author zhoujy
* @date 2018年12月06日
**/
@Component
public class TestServiceImpl implements TestService {
   @Resource
   TestMapper testMapper;

   @Transactional
   public void insertTestInnerInvoke() {
       //正常public修饰符的事务方法
       int re = testMapper.insert(new Test(10,20,30));
       if (re > 0) {
           throw new NeedToInterceptException("need intercept");
       }
       testMapper.insert(new Test(210,20,30));
   }


   public void testInnerInvoke(){
       //类内部调用@Transactional标注的方法。
       insertTestInnerInvoke();
   }

}

测试用例。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

  @Resource
  TestServiceImpl testService;

  /**
   * 测试内部调用@Transactional标注方法
   */
  @Test
  public void  testInnerInvoke(){
      //测试外部调用事务方法是否正常
     //testService.insertTestInnerInvoke();
      //测试内部调用事务方法是否正常
     testService.testInnerInvoke();
  }
}

上面就是使用的测试代码,运行测试知道,外部调用事务方法能够征程开启事务,testMapper.insert(new Test(10,20,30))操作将会被回滚;

然后运行另外一个测试用例,调用一个方法在类内部调用内部被@Transactional标注的事务方法,运行结果是事务不会正常开启,testMapper.insert(new Test(10,20,30))操作将会保存到数据库不会进行回滚。

第三种

事务方法内部捕捉了异常,没有抛出新的异常,导致事务操作不会进行回滚。示例代码如下。

/**
* @author zhoujy
* @date 2018年12月06日
**/
@Component
public class TestServiceImpl implements TestService {
   @Resource
   TestMapper testMapper;

   @Transactional
   public void insertTestCatchException() {
       try {
           int re = testMapper.insert(new Test(10,20,30));
           if (re > 0) {
               //运行期间抛异常
               throw new NeedToInterceptException("need intercept");
           }
           testMapper.insert(new Test(210,20,30));
       }catch (Exception e){
           System.out.println("i catch exception");
       }
   }
   
}

测试用例代码如下。

@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

  @Resource
  TestServiceImpl testService;

  @Test
  public void testCatchException(){
     testService.insertTestCatchException();
  }
}

运行测试用例发现,虽然抛出异常,但是异常被捕捉了,没有抛出到方法 外, testMapper.insert(new Test(210,20,30))操作并没有回滚。

以上三种就是@Transactional注解不起作用,@Transactional注解失效的主要原因。下面结合spring中对于@Transactional的注解实现源码分析为何导致@Transactional注解不起作用。 ———————————————— 版权声明:本文为CSDN博主「一撸向北」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/qq_20597727/article/details/84900994



评论
最新发布
2024-03-31
2024-03-31
2024-03-28
2024-03-28
2024-03-25
2024-03-19
2024-03-19
2024-03-13
2024-03-13
2024-03-12
layui

微信扫码关注DEMO程序园公众号

本周热门
1873
1607
1364
1321
1263
1025
1012
976
856
496
热门下载
27
20
19
14
14
12
12
12
12
11