Spring+Mybatis嵌套事务,在子事务提交后查数据为空
需求场景
public class BServiceImpl implements BSevice{
@Autowired
private ASevice aSevice;
@Resource(name="transactionManager")
private DataSourceTransactionManager transactionManager;
@Transactional(propagation=Propagation.REQUIRED,readOnly=false,rollbackFor=Exception.class)
@Override
public void methonA(Object o) {
//做一些业务处理
methonB(o);
//做一些业务操作
Object two = new Object();
aSevice.qryByObject(two);
}
public void methonB(Object o) {
//做一些处理
aSevice.insert(o);
}
}
public class A{
@Autowired
private ASevice aSevice;
public void methonC(Object o) {
aSevice.qryByObject(two);
}
}
在BSercice的methonA中调用AService的insert()方法,之后再调用AService的qryByObject()方法查询刚插入的数据。A.methonC()可能是通过一些组件调用,如MQ。这样就会出现组件再调用methonC()时methonA的事务还没有提交,查询的数据为空。想到的解决方法是给methonB开启一个新事务手动提交。
public void methonB(Object o) {
DefaultTransactionDefinition def = new DefaultTransactionDefinition();
def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔离级别,开启新事务,这样会比较安全些。
TransactionStatus status = transactionManager.getTransaction(def); // 获得事务状态
try {
aSevice.insert(o);
} catch (Exception e) {
transactionManager.rollback(status);
e.printStackTrace();
}
}
这样有出现新的问题,methonA()中调用aSevice.qryByObject()为空,应该是事务默认是可重复读级别,开启之后其他事务提交的数据也是查不到的。由于项目已经上线,客户比较赶。临时解决方法为给aSevice.qryByObject()也开启一个新事务。
@Transactional(propagation=Propagation.REQUIRES_NEW,readOnly=false,rollbackFor=Exception.class)
@Override
public Object qryByObject(Object o) {
return null;
}
注意propagation=Propagation.REQUIRES_NEW。