Прозрачная запись последнего измененного пользователя на объекте JPA - PullRequest
2 голосов
/ 20 октября 2011

Я нашел метод в ответе ниже очень полезным для прозрачного управления созданной и обновленной отметкой времени для сущностей:

жесткая настройка времени сгенерированного автоматически с аннотациями JPA в спящем режиме

Мне интересно, есть ли что-то подобное для записи пользователя создания и обновления для сущности?

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

Хотя новый Date() в этом примере отображает текущее время, у меня возникают проблемы с поиском места, в котором можно сохранить идентификатор пользователя (во время входа в систему), доступного из аннотированного метода @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 ]

1 голос
/ 20 октября 2011

Если это веб-приложение, вы можете использовать ThreadLocal для хранения текущего пользователя.

  • Установить значение ThreadLocal в фильтре сервлета, считывая пользователя из запроса сервлета.
  • Считайте значение ThreadLocal из ваших объектов JPA.
  • Очистите значение в обратном пути через фильтр.
0 голосов
/ 20 октября 2011

Вы можете вручную внедрить зависимости CDI с помощью пользовательского инжектора 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, но получит все его зависимости(и этим будет управлять cdi).

Сказав это, возможно, есть лучший способ сделать это в зависимости от используемых веб-сред / сред безопасности.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...