You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 03:07:03