springboot事务。

1.查看当前事务管理器是哪种实现方式

	@Resource
	private PlatformTransactionManager platformTransactionManager;

logger.debug("platformTransactionManager:{}", platformTransactionManager);

org.springframework.jdbc.datasource.DataSourceTransactionManager@1fec5522

2.查看当前方法的事务名称和隔离级别

		logger.debug("currentTransactionName:{},level:{}", TransactionSynchronizationManager.getCurrentTransactionName(),
				TransactionSynchronizationManager.getCurrentTransactionIsolationLevel());

currentTransactionName:com.ybjdw.order.spotorder.SV.impl.SpotOrderSVImpl.autoReceipt,level:null;事务名称默认是方法的完全限定名称,隔离级别为null,表示使用数据库的隔离级别,注意mysql只有InnoDB引擎才支持事务

3.方法上的事务注解优先于类上的事务注解。

4.spring一个类中,不同方法使用事务注解(不同传播方式和隔离级别),一个方法调用另一个方法,后面的方法事务使用的是前一个方法事务。

        例子: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。

5.手动设置提交事务

	@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); // 事务提交

6.事务不生效情况

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);
        }
    }

你可能感兴趣的:(java,spring,boot,java,spring)