先看代码,你觉得运行结果是什么?
public class TestService {@Autowiredprivate TestService service;@Transactionalpublic void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}}@Transactionalpublic void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);// 异常代码System.out.println("".substring(4));}
}
答案是test31插入了一条数据,test32也插入了一条数据。
往下看……
一、首先要确保注解是生效的
示例一:
public class TestService1 {@Autowiredprivate TestService2 service2;@Transactional // 生效public void test1(){service2.test2();}
}public class TestService2 {@Transactional // 不生效public void test2() {System.out.println("test2");}
}
这里的test1的@Transactional生效,test2()的@Transactional不生效,嵌套时,只有最外层的生效。
示例二:
public class TestService1 {public void test1(){test2();}@Transactional // 不生效public void test2() {System.out.println("test2");}
}
这里的test2()的@Transactional不生效,原因看后面原理
示例三:
public class TestService1 {@Autowiredprivate TestService1 service;public void test1(){service.test2();}@Transactional // 生效public void test2() {System.out.println("test2");}
}
这里自己注入自己后,就生效了,看下面原理
原理
因为spring里是通过代理类来调用,所以自己注入自己就可以(spring自身解决了循环依赖问题),或者还可以通过获取代理类来调用。
二、代码异常时,执行顺序
从发生异常的地方开始,往上抛
1、如果先遇到try catch,那么就被catch住(如果catch里面不再往外抛异常,那就不会被事务抓到)
2、如果先遇到事务,那就会回滚
三、发生回滚时,哪些代码会被回滚?
会回滚从生效的@Transactional下面的所有内容,包含try catch内容
四、示例
示例一
@Transactional
public void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}// 异常代码System.out.println("".substring(4));
}@Transactional
public void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);
}
结果是,test31的正常代码和test32的正常代码回滚。这里的test31的@Transactional有效,执行异常代码时,会回滚test31里面包含的所有内容,包括try catch里面的test32的内容
示例二
public void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}
}@Transactional
public void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);// 异常代码System.out.println("".substring(4));
}
结果是,test31的正常代码,执行成功,test32的正常代码被回滚
示例三,文章开头的例子
public class TestService {@Autowiredprivate TestService service;@Transactionalpublic void test31() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test1").build();infOrdersmesInMapper.insert(in);try {service.test32();} catch (Exception e) {e.printStackTrace();}}@Transactionalpublic void test32() {// 正常代码InfOrdersmesIn in = InfOrdersmesIn.builder().zbguid(SnowflakeIdWorker.getSnowflakeId()).zernam("test2").build();infOrdersmesInMapper.insert(in);// 异常代码System.out.println("".substring(4));}
}