Quarkus:外层事务回滚时仍执行数据库更新的最佳实践
Quarkus事务回滚时执行MySQL更新的推荐方案
我们的多数Quarkus端点遵循标准实践,使用@Transactional注解调用业务层代码,一旦抛出异常则整个事务回滚:
// Quarkus Resource类 @POST @Transactional @Path("/document/generate") public void generateDocument() { documentGeneratorComponent.generateDocument(...); }
但当前场景下,我们需要在事务回滚时仍执行MySQL 8数据库更新。最初尝试使用@Transactional(REQUIRES_NEW)注解标记状态更新方法,但因外层事务与嵌套事务同时操作同一条跟踪记录,出现锁超时异常:
@ApplicationScoped public class DocumentGeneratorComponent { public void generateDocument(...) { Long trackingId = null; try { trackingId = createTrackingRecord(DocGenStatus.STARTED); // 存在抛出异常风险的操作 var input = getInputData(...); docGenService.sendDocRequest(input); } catch (Exception ex) { if (trackingId != null) { updateStatusWithError(trackingId); } throw ex; } } // 发生异常时更新跟踪记录 @Transactional(REQUIRES_NEW) public void updateStatusWithError(var trackingId) { updateTrackingRecord(trackingId, DocGenStatus.EXCEPTION); } }
曾考虑移除资源层的@Transactional注解,转而在组件内部处理事务,但业务层其他代码可能需要在自身事务范围内调用文档生成功能,这种方案不适用。我们期望有一种类似回调的机制,能在事务回滚时执行指定代码:
public void generateDocument(...) { Long trackingId = null; try { // 业务逻辑执行 } finally { transactionManager.onCurrentTransactionRollback( () -> updateStatusWithError(trackingId) ); // ... } }
也调研过@TransactionScoped bean,但该注解的@PreDestroy存在未修复的行为缺陷;而全局事务监听器会监听应用内所有事务,无法精准针对目标场景使用:
void onAfterEndTransaction(@Observes @Destroyed(TransactionScoped.class) Object event) { // 会被应用中所有事务触发,而非仅目标代码对应的事务 }
请问Quarkus中实现该需求的推荐方案是什么?
内容的提问来源于stack exchange,提问作者nogridbag
相关产品推荐
相关产品推荐

