事务传播性:
事务的传播属性一共有七种,如下。
1、PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
2、PROPAGATION_SUPPORTS:自身不会开启事务,在事务范围内则使用相同事务,否则不使用事务。‘
3、PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
4、PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
5、PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
6、PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
7、PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
而在实际的应用总,只有PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW、PROPAGATION_NESTED这三种是常用的。而第二三种很类似,PROPAGATION_REQUIRES_NEW是无论如何,子方法都会创建一个事务来管理。而PROPAGATION_NESTED则是应用了数据库的保存点技术,和调用它的方法共用同一个事务管理器。
这里有一个坑点,外部经过spring容器调用service的方法事务才生效,service类内部方法间相互调用事务不生效,也就是传说中的自调用失效问题。主要原因是 Spring数据库事务的约定,其实现原理是AOP,而AOP的原理是动态代理,在自调用的过程中,是类自身的调用,而不是代理对象去调用,那么就不会产生AOP,这样 Spring就不能把你的代码织入到约定的流程中,于是就产生了现在看到的失败场景。为了克服这个问题,我们可以用一个 Service去调用另一个 Service,这样就是代理对象的调用, Spring才会将你的代码织入事务流程。当然也可以从 Spring loc容器中获取代理对象去启用AOP。下面我粘了一段代码,通过这种方式,再ioc容器中获取代理对象就可以解决事务传播失效的问题。(具体对于异常是否要捕获,是否要继续抛出,则完全看你业务的需求。)
/**
* <p>
* 服务类
* </p>
*
* @author alin
* @since 2018-12-29
*/
public interface ICityService extends IService<City> {
public void insertAlin01(City city) throws Exception;
public void insertAlin02() throws Exception;
}
@Service
public class CityServiceImpl extends ServiceImpl<CityMapper, City> implements ICityService {
@Autowired
private CityMapper cityMapper;
@Autowired
private IUserService userService;
@Autowired
private ICityService cityService;
@Override
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRED)
public void insertAlin01(City city) throws Exception {
cityMapper.insert(city);
User user = new User();
user.setName("new");
user.setGender(1);
try {
cityService.insertAlin02();
} catch (Exception e) {
}
}
@Override
@Transactional(isolation = Isolation.REPEATABLE_READ, propagation = Propagation.REQUIRES_NEW)
public void insertAlin02() throws Exception {
City city = new City();
city.setName("method2");
city.setAge(2);
city.setState(DateUtil.getStringDate());
cityMapper.insert(city);
}
}
这里只是粗略写了点个人想法,想深入了解一点建议看《深入浅出Spring Boot 2.x》第六章6.4节传播行为的相关讲解。
本文介绍了事务的七种传播属性,重点讨论了PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW和PROPAGATION_NESTED的常见应用场景。提到了一个坑点,即在Spring中,服务类内部方法的自调用会导致事务失效,原因是AOP的动态代理机制。为了解决这个问题,可以通过Spring容器获取服务的代理对象进行调用来启用事务。建议阅读《深入浅出Spring Boot 2.x》了解更多详情。
自调用失效学习笔记&spm=1001.2101.3001.5002&articleId=85417586&d=1&t=3&u=98c370d45bb34b0ca1cadad124b4f175)
5622

被折叠的 条评论
为什么被折叠?



