在JPA实体上透明地记录上次修改的用户

时间:2011-10-20 02:00:19

标签: java jpa

我发现以下答案中的技术对于透明地管理实体的创建和更新时间戳非常有用:

hard time setting autogenerated time with hibernate JPA annotations

我想知道是否有类似的内容记录实体的创建和更新用户?

@PreUpdate
@PrePersist
public void updateAudit() {
    lastModifiedDate = new Date();
    lastModifiedUser = ??;
    if (dateCreated==null) {
      dateCreated = new Date();
      userCreated = ??;
    }
}

虽然示例中的新Date()提供了当前时间,但我无法找到可以存储用户ID的位置(在登录时),该位置可以从实体上的@PrePersist注释方法访问

使用@LoggedInUser方法注入@Produces是理想的,但我的实体是由new()而不是注入创建的,因此不会被管理。

我对此很新,所以我希望我遗漏了一些明显的东西。感谢。

[编辑]下面从prunge回答导致代码(删节)

@MappedSuperclass
public abstract class BaseEntity implements Serializable, Comparable<BaseEntity> {

    @Version
    private Timestamp updatedTimestamp;

    private static ThreadLocal<Long> threadCurrentUserId = new ThreadLocal<Long>();

    /* Called from entry point like servlet 
    */
    public static void setLoggedInUser(BaseEntity user) {
        if (user!=null) threadCurrentUserId.set(user.getId());
    }

    @PrePersist
    @PreUpdate
    protected void onCreateOrUpdate() {
         //Note we don't have to update updatedTimestamp    since the @Version annotation does it for us
         if(createdTimestamp==null) createdTimestamp = new Timestamp(new Date().getTime());;

         lastUpdatedByUserId = threadCurrentUserId.get();
         if(createdByUserId==null)  createdByUserId = lastUpdatedByUserId;
    }

2 个答案:

答案 0 :(得分:1)

如果是webapp,您可以使用ThreadLocal存储当前用户。

  • 在servlet过滤器中设置ThreadLocal值,从servlet请求中读取用户。
  • 从JPA实体中读取ThreadLocal值。
  • 通过过滤器清除行程中的值。

答案 1 :(得分:0)

您可以使用自定义CDI Injector手动注入CDI依赖项,我认为有以下几点:

@Inject
private BeanManager beanManager;    

...

Entity entity = new Entity();

AnnotatedType<?> type = beanManager.createAnnotatedType(class);

InjectionTarget target = beanManager.createInjectionTarget(type);
CreationalContext context = beanManager.createCreationalContext(null);

target.inject(entity, context);

请注意,该实体不会成为CDI托管bean,但会注入所有依赖项(这些将由cdi管理)。

话虽如此,根据您正在使用的Web /安全框架,可能有更好的方法来执行此操作。