首页 > 解决方案 > Spring @Transaction 和 @Async 用于数据库操作

问题描述

在 Spring 应用程序中,当我们收到消息时,@Service 持久 bean 正在调用数据库操作以插入数据库和并行 @Service 以解析和处理消息。在这种情况下,persist 使用@Transactional。为了使流程并行,是否建议添加@Async for persist。

此外,persist 服务调用的每个保存方法都有@Aspect,用于日志记录和审计。

标签: javaspringasynchronousconcurrency

解决方案


@Async 所做的只是导致被注释组件的方法在另一个线程上执行,它从池中获取线程(可以指定,因此您可以为某些操作选择具有专用池)。

@Async 本身不做任何事情来锁定数据库表或任何其他与数据库相关的事情。如果您想要数据库级锁定,则必须通过其他方式实现。如果您希望调用使用事务,则必须在被异步调用的组件上使用 @Transactional 注释。该事务将与调用者的事务分开。当然,根据隔离级别和数据库实现,事务可能会导致数据库锁定。

将@Async 用于数据库工作很棘手。跨线程传递的 jpa 持久实体发生了一个陷阱,当它们具有在新线程中实现的惰性属性时(代理现在无效,因为它无法从旧线程到达 entityManager)。如果线程之间传递的东西是不可变的,那就更安全了。

@Async 增加了复杂性并且很难推理。存在竞争条件和死锁的机会,如果您没有完全正确地解决问题,那么可能会发生坏事,并且您不能指望通过测试来发现问题。它在没有网络的情况下工作,如果您想要任何基础设施来帮助处理异常、重试或其他恢复,您必须自己提供。

所以不,我不一定认为它是可取的。在您的工具箱中拥有它是一项很好的功能,它可能对一些孤立的案例有所帮助,但普遍使用似乎是一件坏事。如果您正在寻找在不阻塞的情况下持久保存数据的方法,还有其他选择。


推荐阅读