如何将参数传递给回调方法

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

我有一个要求,我必须存储每个插入/更新/删除的审计信息。要存储的信息将是更新时间和用户ID。

我从this tutorial学到了我可以使用实体监听器和回调方法,如@PrePersist

我知道如何处理回调方法中的更新时间,但我不知道如何在回调方法中的实体中设置userId:

@PrePersist
private void prePersist() {
   this.updateTime = new Date();
   this.userId = ???;
}

如何将当前用户的ID传递给回调方法?

java hibernate jpa callback
1个回答
1
投票

您无法直接使用Hibernate或JPA API将任何信息传递给回调方法。

但还有另一种常见的解决方案:ThreadLocal

ThreadLocal为当前运行的线程存储静态变量。由于请求通常只在一个线程中执行,因此您可以从回调方法/侦听器访问该信息。一些UI框架为您创建了ThreadLocal

例如,JSF提供了一个FacesContext.getCurrentInstance()。所以在JSF中你可以调用:

FacesContext.getCurrentInstance().getExternalContext().getRemoteUser()

或者在春天与RequestContextHolder

((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest().getRemoteUser()

如果你没有这样的框架,你可以建立自己的ThreadLocal

public final class UserIdHelper {
  // You can add the static ThreadLocal to any class, just as an example
  private static final ThreadLocal<String> userIds = new ThreadLocal<>();

  public static void setCurrentUserId(String userId) {
    userIds.set(userId);
  }

  public static String getCurrentUserId() {
    return userIds.get();
  }

  public static void removeCurrentUserId() {
    userIds.remove();
  }
}

现在,您可以在Filter或JPA调用周围设置userId:

UserIdHelper.setCurrentUserId(request.getRemoteUser());
try {
  // ... Execute your JPA calls ...
} finally {
  UserIdHelper.removeCurrentUserId();
}

删除finally块中的userId很重要 - 否则在同一个线程中运行的后续请求可能会“劫持”您之前的userId。

要在回调方法中访问该信息:

@PrePersist
private void prePersist() {
  this.createdBy = UserIdHelper.getCurrentUserId();
}
© www.soinside.com 2019 - 2024. All rights reserved.