目录
1. 增加一个service,把一个事务的方法移到新增加的service方法里面,然后进行注入再调用
一、方法内部调用
在同一个类的service中,调用其他的事务方法
@Service
public class DemoService {
@Transactional
public void query(Demo demo) {
save(demo) ;
}
@Transactional
public void save(Demo demo) {
}
}
可以看到,query方法调用了save的方法,由于spring的事务实现是因为aop生成代理,这样是直接调用了this对象,所以也不会生成事务。
1、原理:
当spring容器启动的时候,发现有@EnableTransactionManagement注解,此时会拦截所有bean的创建,然后会扫描一下bean上是否有@Transaction注解(类、接口、或者方法上有这个注解都可以),如果有这个注解,spring会通过aop的方式给这个bean生成代理对象(代理对象中存在本类对象),代理对象中会增加一个拦截器,拦截器会拦截bean中public方法的执行,会在方法执行前启动事务,方法执行完毕之后提交或者回滚事务。
2、结论:
如果A和B两个方法在同一个类中
1、如果A加了@Transaction注解,B上有没有@Transaction注解,事务都是有效的,则AB 在同一个事务中。2、如果A不加@Transaction注解,B上有没有@Transaction注解,事务都是无效的。
如果A和B两个方法不在同一个类中
1、如果A加了@Transaction注解,B上有没有@Transaction注解,事务都是有效的。2、如果A不加@Transaction注解,B加了@Transaction注解,只有B是有事务的。
3、如果A不加@Transaction注解,B也不加@Transaction注解,A和B都是没有事务的。
简单理解:
在同一个类中,只要A加了@Transaction注解,无论B加不加注解,AB都在同一个事务中,事务有效。
如果AB在同一个类中,A不加注解,B加了注解,则事务失效;如果AB不同类,A不加注解,B加了注解,则只有B有事务。
原因分析:
在A方法有@Transaction注解时,spring在管理的时候会生成一个代理类,在外部调用A方法时,实际执行的是代理类里面的方法,该代理类里面的方法已经包括了B方法的调用,已经成为了一个方法,所以事务是有效的。
3、解决方法:
1. 增加一个service,把一个事务的方法移到新增加的service方法里面,然后进行注入再调用
@Service
public class DemoTwoService {
@Transactional
public void save(Demo demo) {
}
}
@Service
public class DemoService {
@Autowired
DemoTwoService demoTwoService;
@Transactional
public void query(Demo demo) {
demoTwoService.save(demo);
}
}
2. 在自己类中注入自己
@Service
public class DemoService {
@Autowired
DemoService demoService;
@Transactional
public void query(Demo demo) {
demoService.save(demo);
}
@Transactional
public void save(Demo demo) {
}
}
由于这种写法基于spring的三级缓存不会导致,循环依赖的问题出现