CompletableFuture 多线程事务
码示例代码示例
@Resource
private PlatformTransactionManager transactionManager;
@Transactional(rollbackFor = Exception.class)
public String uploadBodyFatScaleData(Long patientUserId, AppBodyFatAddReqVO createReqVO) {
// 插入
BodyFatDO bodyFat = BodyFatConvert.INSTANCE.convert(createReqVO);
//设置患者id
PatientUserDO patient = patientUserService.getPatient(patientUserId);
String patientId = patient.getPatientId();
bodyFat.setPatientId(patientId);
bodyFatMapper.insert(bodyFat);
//使用一个线程池执行异步任务
ThreadPoolExecutor executor = ExecutorBuilder.create()
.setCorePoolSize(FIVE_INTEGER)
.setMaxPoolSize(TEN_INTEGER)
.build();
TransactionTemplate transactionTemplate = new TransactionTemplate(transactionManager);
//更新患者最后活动时间
CompletableFuture<Void> updateLastActiveTimeTask = CompletableFuture.runAsync(() -> {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(@NonNull TransactionStatus status) {
patientUserService.updateTheLastActiveTime(patientUserId);
}
});
}, executor);
//更新患者初始体重和现在体重
double weight = createReqVO.getWeight();
double patientUserMinWeight = patient.getMinWeight();
double patientUserMaxWeight = patient.getMaxWeight();
Long numberOfWeighing = getNumberOfWeighingByPatientId(patientId);
CompletableFuture<Void> updateWeightTask = CompletableFuture.runAsync(() -> {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(@NonNull TransactionStatus status) {
patientUserService.updatePatientInitialAndCurrentAndMinAndMaxWeight(
patientUserId, weight,
//patientUserMinWeight小于等于当前体重的话就拿现在体重
Math.min(Math.min(patientUserMinWeight, weight), weight),
Math.max(patientUserMaxWeight, weight),
getFirstWeighing(patientId),
numberOfWeighing);
}
});
}, executor);
// 新增历史记录
CompletableFuture<Void> addHistoryTask = CompletableFuture.runAsync(() -> {
transactionTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(@NonNull TransactionStatus status) {
AddHistoryUtil.addHistory(EventRecordEnums.WEIGHT, patient.getId(),
String.valueOf(createReqVO.getWeight()),
RecordTypeEnum.WEIGHT.getValue(),
createReqVO.getMeasuringTime());
}
});
}, executor);
//等待所有任务完成后返回结果
return CompletableFuture.allOf(updateLastActiveTimeTask, updateWeightTask, addHistoryTask)
.thenApply(v -> bodyFat.getId())
.join();
}
在这段代码中,@Transactional 注解用于管理 uploadBodyFatScaleData 方法的事务。但是,使用 CompletableFuture.runAsync 与自定义的 ThreadPoolExecutor 异步执行任务意味着这些任务在原始事务的范围之外执行。
相反,创建了一个新的 TransactionTemplate 并用于在它们自己的事务中执行这些任务。这意味着每个任务都在其自己的事务中执行,独立于由 @Transactional 注解管理的原始事务。
因此,在这段代码中,异步任务的事务将按预期工作,但它们将与由 @Transactional 注解管理的原始事务分开。
TransactionTemplate 是 如何工作的?
TransactionTemplate 是一个模板类,它简化了编程式事务划分和事务异常处理。它的核心方法是 execute,它支持实现 TransactionCallback 接口的事务代码。此模板处理事务生命周期和可能的异常,因此无需显式处理事务,既不需要 TransactionCallback 实现,也不需要调用代码 ¹。
要使用它,我们应该首先使用 PlatformTransactionManager 对其进行初始化。我们可以使用依赖注入来设置此模板 ¹。
例如:
@Autowired
private PlatformTransactionManager transactionManager;
private TransactionTemplate transactionTemplate;
@BeforeEach
void setUp() {
transactionTemplate = new TransactionTemplate(transactionManager);
}
(3) 深入理解TransactionTemplate编程式事务 - CSDN博客. https://blog.csdn.net/qq_33404395/article/details/83377382.

浙公网安备 33010602011771号