简介:
失效场景介绍
第一种
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版权协议,转载请附上原文出处链接及本声明。 原文链接: