Сбой аудита Spring Data JPA при сохранении отключенного объекта

Я установил аудит JPA с помощью Spring Data JPA AuditingEntityListener и AuditorAware bean. Я хочу иметь возможность сохранять данные аудитора даже для сущностей с предопределенными идентификаторами. Проблема в том, что когда объект JPA с предопределенным идентификатором сохраняется и сбрасывается, данные аудитора не могут быть сохранены:

объект ссылается на несохраненный временный экземпляр - сохраните временный экземпляр перед сбросом: me.auditing.dao.AuditorDetails

Интересно то, что когда сущность со сгенерированным идентификатором сохраняется - все в порядке. В обоих случаях объекты новые. Я не смог точно определить проблему, копаясь в коде гибернации, поэтому я создал образец проекта, чтобы продемонстрировать это (тестовый класс me.auditing.dao.AuditedEntityIntegrationTest) В нем есть как объекты с предопределенными, так и сгенерированными идентификаторами, и он должен подвергаться аудиту.

Сущности:

@Entity
public class AuditedEntityWithPredefinedId extends AuditableEntity {

    @Id
    private String id;

    public String getId() {
        return id;
    }

    public AuditedEntityWithPredefinedId setId(String id) {
        this.id = id;
        return this;
    }
}

а также:

@Entity
public class AuditedEntityWithGeneratedId extends AuditableEntity {

    @Id
    @GeneratedValue(generator = "uuid")
    @GenericGenerator(name = "uuid", strategy = "uuid")
    private String id;

    public String getId() {
        return id;
    }

    public AuditedEntityWithGeneratedId setId(String id) {
        this.id = id;
        return this;
    }
}

где родительский класс:

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class AuditableEntity implements Serializable {

    private static final long serialVersionUID = -7541732975935355789L;

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    @CreatedBy
    private AuditorDetails createdBy;

    @CreatedDate
    private LocalDateTime createdDate;

    @ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.ALL})
    @LastModifiedBy
    private AuditorDetails modifiedBy;

    @LastModifiedDate
    private LocalDateTime modifiedDate;

И реализация геттера аудитора:

@Override
public AuditorDetails getCurrentAuditor() {
    return new AuditorDetails()
            .setId(null)
            .setUserId("someUserId")
            .setDivisionId("someDivisionId");
}

Редактировать 08.08.2016: Похоже, что когда новая сущность с предопределенным идентификатором сохраняется, она получает два разных экземпляра createdBy и modifiedBy AuditorDetails, что вполне логично, если сущность на самом деле не новый. Таким образом, совершенно новый объект со сгенерированным именем получает AuditorDetails одного и того же экземпляра, а объект с идентификатором, установленным вручную, - нет. Я протестировал его, сохранив детали аудитора в bean-компоненте AuditorAware, прежде чем возвращать его в AuditingHandler.


person J R    schedule 08.08.2016    source источник


Ответы (1)


Итак, на данный момент единственное решение, которое я смог найти, - это сохранить AuditorDetails перед записью его в проверяемые объекты, например:

@Override
@Transactional
public AuditorDetails getCurrentAuditor() {
    AuditorDetails details = new AuditorDetails()
            .setId(null)
            .setUserId("someUserId")
            .setDivisionId("someDivisionId");
    return auditorDetailsRepository.save(details);
}

Это не самое элегантное решение, но пока оно работает.

person J R    schedule 09.08.2016