异步上传,手动回滚、脱离Spring事物

需求场景:
Excel数据录入到数据库,由于校验比较多需要异步处理,并且保留错误信息履历维护到数据库。

解决思路:
首先保留错误信息到数据库就有个很麻烦的点,由于导入时有及其复杂的嵌套逻辑可能需要优先插入数据下面的任务才能进行,而且还要求excel每一条全部录入完一次记录所有错误信息,这就需要事物回滚了,而保存错误信息这个动作由于事物的一致性也会被回滚,所以还要控制事物,让其提交一部分回滚一部分。

1.Excel文件异步提交

controller层


	@PostMapping("/import")
	public R importDevice(@RequestPart MultipartFile file) throws Exception {
		// 在进入实现类之前获取MultipartFile的文件流,要做异步处理就不能在线程里获取流
		InputStream inputStream = file.getInputStream();
		projectService.importDevice(inputStream);
		return R.ok();
	}

service接口


	@Async
	void importDevice(InputStream inputStream) throws Exception;
	

@Async详解

如果直接把MultipartFile交给Service异步处理直接就报NoSuchFileException异常,原因是主线程Controller中的MultipartFile生成实例同时会生成临时文件,MultipartFile的实例交给异步线程Service处理前Controller瞬间执行结束MultipartFile临时文件会被springboot(spring)销毁,所以子线程获取不到InputStream

解决方案:在主线程中获取MultipartFileInputStream,这样子线程中InputStream流作为了入参,就不会产生找不到文件的情况。

2.手动回滚

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void importDevice(InputStream inputStream) {
		TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
	}
	

搭配@Transactional使用。事物出现异常又需要try catch 捕获时,事物注解回滚会失效(try catch脱离Spring管理),手动回滚可以在任何情况下回滚包括try catch

3.脱离Spring事物

业务场景:由于一些必要提交的信息需要在回滚的状态下一样提交,就需要脱离事物形成自定义回滚部分。


		// 建立可控任务用于在子线程获取返回数据
		FutureTask<Long> futureTask = new FutureTask(() -> importLogService.importRecord(importLog, null));
		// 控制子线程脱离Spring事物
		new Thread(futureTask).start();
		importLog.setId((futureTask.get()));
		
  • 建立一个子线程就不会被Spring管理了,把必须提交的任务放在子线程里就不会被回滚
  • 需要在子线程里获取返回值可以建立可控任务,在把任务放到子线程去执行就能获取子线程里获取返回值
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值