java 在Sping Boot 中使用@Transactional时,如何在审计表中持久化数据?

gjmwrych  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(227)

我们有多个依赖的API在循环内调用,我们需要在一个Audit表中持久化每个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
}
wljmcqd8

wljmcqd81#

这是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方法的运行时参数,可以使用this answer
请注意,spring-aop只适用于代理方法。它不会拦截任何private secondApiImplementation()

相关问题