栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Spring事务传播行为-编程式事务

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Spring事务传播行为-编程式事务

1、 编程式事务

Spring 事务管理有两种方式:

编程式事务:通过编码方式实现事务;

声明式事务:基于AOP实现,如 @Transactional 声明式注解。

2、 实现原理

编程式事务基于TransactionTemplate实现,TransactionTemplate继承TransactionOperations接口

TransactionOperations提供有返回结果执行事务操作和无返回结果执行事务操作

TransactionOperations 默认实现 executeWithoutResult 方法

public interface TransactionOperations {
	
	@Nullable
	 T execute(TransactionCallback action) throws TransactionException;

	
	default void executeWithoutResult(Consumer action) throws TransactionException {
		execute(status -> {
			action.accept(status);
			return null;
		});
	}

}

TransactionTemplate 实现 execute 方法

public class TransactionTemplate extends DefaultTransactionDefinition
		implements TransactionOperations, InitializingBean {
	
	@Nullable
	private PlatformTransactionManager transactionManager;	

	
	public TransactionTemplate(PlatformTransactionManager transactionManager) {
		this.transactionManager = transactionManager;
	}	


	@Override
	@Nullable
	public  T execute(TransactionCallback action) throws TransactionException {
		Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");

		if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
			return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);
		}
		else {
			TransactionStatus status = this.transactionManager.getTransaction(this);
			T result;
			try {
				result = action.doInTransaction(status);
			}
			catch (RuntimeException | Error ex) {
				// Transactional code threw application exception -> rollback
				rollbackOnException(status, ex);
				throw ex;
			}
			catch (Throwable ex) {
				// Transactional code threw unexpected exception -> rollback
				rollbackOnException(status, ex);
				throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
			}
			this.transactionManager.commit(status);
			return result;
		}
	}

}

3、编程式事务例子

3.1 编程式事务带返回值

CarOrderReplaceSubmitServices 订单提交

@Service
public class CarOrderReplaceSubmitServices implements CarOrderSubmitServices {
    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private CarOrderDao carOrderDao;

    @Override
    public Integer submit(CarOrderSubmitReqDto reqDto) {
        CarOrderEntity carOrderEntity = new CarOrderEntity();
        carOrderEntity.setOrderNo(reqDto.getOrderNo());
        carOrderEntity.setCarNo(reqDto.getCarNo());
        
        Integer id = transactionTemplate.execute(transactionStatus -> {
            // 执行数据库事务操作
            carOrderDao.add(carOrderEntity);
            Integer tempId = carOrderEntity.getId();
            this.updateStock(carOrderEntity, 1);
            return tempId;
        });
        return id;
    }

    @Override
    public void updateStock(CarOrderEntity carOrderEntity, Integer stockCount) {
        // 声明式事务注解事务依旧有效
        carOrderDao.updateStockByCarNo(carOrderEntity.getCarNo(), stockCount);
    }
}

CarOrderDaoImpl 实现库存更新

@Service
public class CarOrderDaoImpl extends
        ServiceImpl implements
        CarOrderDao {   
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = {Exception.class,RuntimeException.class})
    public boolean updateStockByCarNo(String carNo, Integer stockCount) {
        CarOrderEntity carOrderEntity = new CarOrderEntity();
        carOrderEntity.setStockCount(stockCount);
        LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CarOrderEntity::getCarNo, carNo);
        return super.baseMapper.update(carOrderEntity, wrapper) > 0;
    }   
}

在更新库存时使用声明时事务注解,事务传播行为依然有效:

3.1.1 REQUIRED

submit方法: 事务传播行为 Propagation.REQUIRED

updateStockById方法:  事务传播行为 Propagation.REQUIRED

结论:在同1个事务内一起提交

原因:因为submit已经存在事务,所以使用同1个事务

3.1.2 REQUIRES_NEW

submit方法: 事务传播行为 Propagation.REQUIRED

updateStockById方法:  事务传播行为 Propagation.REQUIRES_NEW

结论:不在同1个事务内,updateStockById更新时会死锁,等待submit提交,造成相互等待

原因:REQUIRES_NEW模式新建事务,如果当前存在事务,把当前事务挂起

其他事务传播行为的实践见: Spring事务传播行为-声明式事务

3.2  编程式事务不带返回值

        
        transactionTemplate.executeWithoutResult(t -> {
            // 执行数据库事务操作
            carOrderDao.add(carOrderEntity);
            this.updateStock(carOrderEntity, 1);
        });

 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1004013.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号