在Spring Boot中使用@Transactional时如何将数据持久化到审计表中?

问题描述 投票:0回答:1

我们有多个在循环内调用的依赖 API,我们需要将每个 API 响应保存在一个审核表中。现在,我们面临一个问题,比如如果第一个 API 抛出一些异常(400/500...),我们需要在审计表中至少存储审计数据,但由于 @Transactional,它正在滚动审计表数据而且我们不想回滚这些数据。

请提出需要的建议。

我们尝试过,但没有成功

@Transactional(propagation = Propagation.NEVER)

@Transactional(propagation = Propagation.NOT_SUPPORTED)

对于 NOT_SUPPORTED,将停止继续进行。


@Transactional
public void apiImplementation() {
   auditService.addDataInAuditTable("123","...");
   boolean isLastPage = true;
   int currentPage = 0;
   do {
    ResponseEntity<AbcModel> response = restApiService
            apiCallToGetAbcDetails(100, currentPage++);
    if (response != null && response.getStatusCode() == HttpStatus.OK) {
        AbcModel abcModel = response.getBody();
        if (abcModel != null) {
        isLastPage = abcModel.isLastPage();
        abcModel.getData.forEach(this::secondApiImplementation);
         }
    }
    } while (!isLastPage);
}               
    
private void secondApiImplementation(AbcModel abcModel) {
    here we're saving data and calling the second Api... and also save data in auditlog for second api
}
java spring-boot transactions rollback
1个回答
0
投票

这是

spring-aop
的典型用例。

如果您只有一种方法来处理所有方法的错误,本质上您将使用

@Auditable

定义您的审核方法
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface Auditable{}

@Transactional
@Auditable
public void apiImplementation(){
  // Stuff
}

然后在你的

Aspect

@Aspect
@Component
public class AuditAspect {

  @Around("@annotation(auditable)")
  public void audit(ProceedingJoinPoint joinPoint) throws Throwable {
    try{
      // You can audit before if you would like
      joinPoint.proceed();
    } finally {
    //Do your thing here (call another service/repository or private methods). You will audit regardless of the method execution.
    }
  }
}

如果您还想审核 API 的响应,您还可以捕获

proceed()
的结果。 如果你想检索 api 方法的运行时参数,你可以使用 这个答案

请注意,

spring-aop
仅适用于代理方法。它不会拦截任何
private secondApiImplementation()

© www.soinside.com 2019 - 2024. All rights reserved.