简体   繁体   中英

How to pass a parameter to a callback method

I have a requirement where I have to store audit information for every insert/update/delete. Info to be stored will be update time and user id .

I learned from this tutorial that I can use entity listeners and callback methods like @PrePersist .

I know how to handle the update time inside the callback methods but I don't know how I can set the userId in entity inside the callback methods:

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

How can I pass the ID of the current user to callback methods?

You can't pass any information to the callback methods with the Hibernate or JPA API directly.

But there is another common solution: ThreadLocal

A ThreadLocal stores a static variable for the current running thread. And as a request is usually executed in exactly one thread, you can access that information from your callback method / listener. Some UI framework create already a ThreadLocal for you.

For example JSF provides one with FacesContext.getCurrentInstance() . So in JSF you could call:

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

Or in Spring with the RequestContextHolder :

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

If you've got no such framework you can build your own 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();
  }
}

Now you can set the userId in a Filter or just around your JPA calls:

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

It is important to remove the userId in the finally block - otherwise a follow up request running in the same thread could "hijack" your previous userId .

To access that information in your callback method:

@PrePersist
private void prePersist() {
  this.createdBy = UserIdHelper.getCurrentUserId();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM