先看代码案例
@Transactional(rollbackFor = Exception.class)
public boolean inStore(StoreLogReq req) {
ExecutorService executor = Executors.newFixedThreadPool(2);
executor.submit(() -> {
List<StorageLog> list = new ArrayList<>();
//增加入库记录
for (material a :
req.getMaterial()) {
StorageLog storageLog = new StorageLog();
storageLog.setMaterialId(a.getMaterialId());
list.add(storageLog);
}
mapper.insertBatch(list);
});
executor.submit(() -> {
//根据货架和物料获取货位去亮灯
//亮灯操作
System.out.println(亮灯操作);
throw new RuntimeException(入库失败----------------入库失败);
});
executor.shutdown();
return false;
}
其中抛出异常throw new RuntimeException("入库失败----------------入库失败");的确会导致事务回滚,但是代码中没有捕获这个异常,所以它会在子线程中抛出并终止线程。使用并没有实现真正的事务回滚,在使用线程池时,我们无法直接捕获子线程中的异常,因此需要使用Future来获取子线程的执行结果,并在主线程中处理异常情况。以下是修改后的代码示例:
@Transactional(rollbackFor = Exception.class)
public boolean inStore(StoreLogReq req) {
ExecutorService executor = Executors.newFixedThreadPool(2);
try {
Future<?> future1 = executor.submit(() -> {
// 增加入库记录
// ...
mapper.insertBatch(list);
});
Future<?> future2 = executor.submit(() -> {
// 亮灯操作
// ...
throw new RuntimeException(入库失败----------------入库失败);
});
// 等待所有子线程执行完毕
future1.get();
future2.get();
} catch (Exception e) {
// 捕获子线程抛出的异常并处理
e.printStackTrace();
throw new RuntimeException(入库失败);
} finally {
executor.shutdown();
}
return false;
}
在修改后的代码中,我们使用Future对象来获取子线程的执行结果。通过future.get()方法来等待子线程执行完毕,如果子线程抛出异常,则在主线程中捕获并处理异常。