@Resource
private PlatformTransactionManager platformTransactionManager;
logger.debug("platformTransactionManager:{}", platformTransactionManager);
org.springframework.jdbc.datasource.DataSourceTransactionManager@1fec5522
logger.debug("currentTransactionName:{},level:{}", TransactionSynchronizationManager.getCurrentTransactionName(),
TransactionSynchronizationManager.getCurrentTransactionIsolationLevel());
currentTransactionName:com.ybjdw.order.spotorder.SV.impl.SpotOrderSVImpl.autoReceipt,level:null;事务名称默认是方法的完全限定名称,隔离级别为null,表示使用数据库的隔离级别,注意mysql只有InnoDB引擎才支持事务。
例子:autoReceipt方法调用confirmReceipt方法。
@Override
@Transactional
@Async
public void autoReceipt() throws Exception
{
confirmReceipt("123456");
}
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW, isolation = Isolation.SERIALIZABLE)
public String confirmReceipt(String orderId) throws Exception
{
}
查看方法中的事务信息,发现两个方法使用的事务都是com.ybjdw.order.spotorder.SV.impl.SpotOrderSVImpl.autoReceipt,这是因为spring采用动态代理机制来实现事务控制,事务方法内调用另一个方法,使用的是代理类到数据库的同一个连接。
解决方法:在调用第二个方法时,通过ApplicationContext获取代理类,再次开启代理类到数据库的连接。
@Autowired
private ApplicationContext applicationContext;
ISpotOrderSV spotOrderSV = applicationContext.getBean(ISpotOrderSV.class);
spotOrderSV.confirmReceipt(spotOrder.getOrderId());
这时查看两个方法的事务信息,会发现两个方法的事务名称不一样了,分别com.ybjdw.order.spotorder.SV.impl.SpotOrderSVImpl.autoReceipt和com.ybjdw.order.spotorder.SV.impl.SpotOrderSVImpl.confirmReceipt。
@Resource
private DataSourceTransactionManager dataSourceTransactionManager;
DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_NESTED); // 设置传播行为
defaultTransactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED); // 设置隔离级别
TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(defaultTransactionDefinition);
SpotOrder tmpOrder = new SpotOrder();
tmpOrder.setOrderId("01075604656");
tmpOrder.setOrderState(1);
mapper.updateByPrimaryKeySelective(tmpOrder);
int num = 1/0;
dataSourceTransactionManager.commit(transactionStatus); // 事务提交
1.事务方法捕获了异常,未再抛出异常;在下面方法中catch后未再抛出异常;
@Transactional
@Override
public int reduceStock(String invId, int stockNum) {
int ret=0;
try{
ret = unusualMapper.updateInventoryAmount(invId, stockNum);
return ret;
}catch (Exception e){
logger.error("扣减库存异常!", e);
}
return ret;
}
2.事务方法捕获异常后,再次抛出的异常与默认回滚异常不一致。
@Transactional
@Override
public int reduceStock(String invId, int stockNum) throws Exception{
int ret=0;
try{
ret = unusualMapper.updateInventoryAmount(invId, stockNum);
return ret;
}catch (Exception e){
logger.error("扣减库存异常!", e);
throw new Exception("扣减库存异常", e);
}
}
spring事务回滚默认只会发生在RuntimeException和Error,不会发生在检查异常(即Exception);解决方法为调整rollbackFor参数,如下即可。
@Transactional(rollbackFor = Exception.class)
@Override
public int reduceStock(String invId, int stockNum) throws Exception{
int ret=0;
try{
ret = unusualMapper.updateInventoryAmount(invId, stockNum);
return ret;
}catch (Exception e){
logger.error("扣减库存异常!", e);
throw new Exception("扣减库存异常", e);
}
}