同一个Service内部调用开启事务
同一个Service内部调用开启事务
事务是基于代理实现的,方法内部调用正常情况下是不走代理的,所以如果是子方法开启事务,正常情况下是不生效的
下面的代码,从Controller层去调用,最终还是会插入数据
@Service
public class CliServiceImpl extends ServiceImpl<CliMapper, Cli> implements CliService {
@Override
public ResultObj<Object> add() {
test();
return ResultObj.success();
}
@Transactional(rollbackFor = Exception.class)
public void test() {
Cli cli = new Cli();
cli.setName(UUID.fastUUID().toString());
this.save(cli);
if (true) {
throw new RuntimeException("xx");
}
}
}
关于事务的的原理参看这里
- Spring使用@Transactional 管理事务,Java事务详解
- Spring事务源码解析【一次一篇文章弄懂】
如果我们非要让上面的事务生效,也不是没有办法,改为通过代理调用
方式一:AopContext
// 之前
test();
// 之后
((CliServiceImpl) AopContext.currentProxy()).test();
需要额外加入pom和在启动类开启
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
@SpringBootApplication
@MapperScan("com.xdx97.cli.mapper")
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
public class App {
public static void main(String[] args) {
SpringApplication.run(App.class, args);
}
}
方法二:ApplicationContext
@Autowired
private ApplicationContext applicationContext;
CliServiceImpl proxy = applicationContext.getBean(CliServiceImpl.class);
proxy.test();
注: 这两种方式 并不是创建的新代理对象,是从容器里面拿到的,而对象几乎都是单例的,就不用担心频繁的创建和销毁对象