最近做了分布式的项目,当然没有设计分布式事务的处理,一条逻辑线太长,方法调方法,所以之间的事务问题就暴露出来了
我已阵亡,直接码代码吧
@Service
public class TransactionalServiceImpl implements TransactionalService {
@Autowired
private CgpMngUserbraService cgpMngUserbraService;
@Transactional
@Override
public void method() {
List<CgpMngUserbra> cgpMngUserbras = cgpMngUserbraService.selectUserBraRules(0, 0);
if (null == cgpMngUserbras || 0 == cgpMngUserbras.size()) {
cgpMngUserbraService.insertUserBraRules(0, 0, "method");
}
method2();
}
// @Transactional//此处事务不会生效,原因可阅读上一篇博客
// 传送门---> https://blog.csdn.net/fanxb92/article/details/81296005
public void method2() {
List<CgpMngUserbra> cgpMngUserbras = cgpMngUserbraService.selectUserBraRules(0, 0);
if (null == cgpMngUserbras || 0 == cgpMngUserbras.size()) {
cgpMngUserbraService.insertUserBraRules(0, 0, "method2");
}
TransactionalServiceImpl transactionalService = (TransactionalServiceImpl) AopContext.currentProxy();
transactionalService.method3();
}
@Transactional
// @Transactional(propagation = Propagation.REQUIRES_NEW)
// @Transactional(propagation = Propagation.NESTED)
public void method3() {
List<CgpMngUserbra> cgpMngUserbras = cgpMngUserbraService.selectUserBraRules(0, 0);
if (null == cgpMngUserbras || 0 == cgpMngUserbras.size()) {
cgpMngUserbraService.insertUserBraRules(0, 0, "method3");
}
}
}
先介绍一下测试逻辑:method,method2,method3三个方法都会在一张表保存同一条数据,并且链式调用。
method2加事务是不生效的,method2中事务和method中保持一致,参照代码中博客链接。
method3上面三种事务处理方式
第一种@Transactional,method3中事务和前面保持一致(method方法上注解产生的事务中),全部执行完毕,数据库中一条数据。
一定是全部执行完毕哦,中途打断点,method中还为插入到数据库,因为方法未结束,未commit。
第二种@Transactional(propagation = Propagation.REQUIRES_NEW),method3开启了一个新的事务,会将已有的事务挂起,
同样,方法全部执行完毕后数据库两条数据,数据库记录截图如下:
可见,是method中数据入库时间在前,分析===>
!!!!!!!!!此处非常重要,可能说的不太简洁精确,仔细体会!!!!!!!!!!!!!!!!!!
method中执行insert,但未commit,未插入到数据库
method3中执行insert,执行完毕commit,数据库中会先插入记录(在method3结束但method未结束的地方打断点,会看到数据库已经有记录了),
同时method方法也结束,method事务commit,数据库中插入记录。(method3是新事务,同一事务会查询缓存,所以不在同一个事务中也没有啦,查询数据库是没有记录的,也会入库)。
开启新事务,方法执行完毕就会提交,数据库中有记录,与前面事务不影响。但插入时间,看代码具体逻辑,在前的插入时间在前。
第三种@Transactional(propagation = Propagation.NESTED)
抛出异常JpaDialect does not support savepoints - check your JPA provider's capabilities
public JpaTransactionManager() {setNestedTransactionAllowed(true);}
后来才知道Hibernate也不支持Nested Transaction,测试不了,只能用jdbc事务了,使用JdbcTemplate。
好吧,就先聊这么多吧。谢谢阅读。