我们在业务层方法上使用Spring @Transactional
注释。当我们转移到Java 8时,这些方法已经转换为使用Java 8的Async功能并使用可完成的Futures并将几个异步调用链接到数据层。例如。
@Transactional
public CompletableFuture<Entity> updateEntity(ID id) {
repository1.get(id)
.thenComposeAsync(item -> repository1.save(), executor);
}
上面的代码演示了我们想要链接多个数据库层异步调用。
此@Transactional
注释似乎仅支持阻止调用,并且所有事务上下文信息都保存在ThreadLocal
中。上述方法创建了3个事务。一旦返回未来,外部事务就会启动并完成。 repository1.get(id)
在另一个交易中运行,repository1.save()
在其自己的交易中运行。
是否有一种标准方法可以在单个事务中运行多个异步调用,而无需重写事务拦截器。似乎我们需要将TransactionSynchronizationManager
中的线程局部变量从一个线程复制到另一个线程,以使其在单个事务中执行。
如果他们计划增强spring-tx以支持这个用例,那么感谢Spring团队的反馈。
答案 0 :(得分:0)
我在problem I was trying to solve中遇到了类似的障碍。
简而言之:
TransactionSynchronizationManager
并通过黑客解决方法解决,大多数TransactionManagers都不是为了应对我在单个线程中的事务对象看起来大致如下:
@Service
public class TransactionalObject {
@Autowired
private BlockingQueue<Runnable> queue;
@Transactional
public void consumeTransactionalRunnables() {
try {
while (!Thread.currentThread().isInterrupted()) {
Runnable execution = queue.take();
if (execution instanceof StopExecution) {
return;
}
execution.run();
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
这个对象在它自己的线程上,生成器线程put
到BlockingQueue queue
。此代码示例中的poison pill是StopExecution
Runnable类型。
我发现这个解决方案具有最小的性能开销(与其他选项相比),易于管理,易于阅读和微创。