Я настроил аудит JPA с помощью Spring Data JPA AuditingEntityListener и AuditorAware bean. Я хочу, чтобы иметь возможность сохранять данные аудитора даже на объектах с предопределенными идентификаторами. Проблемы заключается в том, что, когда JPA объект с предопределенным идентификатором в настоящее время сохраняется и продувает его аудиторские детали не могут быть сохранена:Spring Data JPA аудит терпит неудачу, когда сохраняется удаленный объект
ссылки на объекты неспасенной переходная экземпляры - сохранить переходный экземпляр перед промывкой: me.auditing.dao.AuditorDetails
Интересная часть заключается в том, что когда объект с сгенерированным идентификатором сохраняется - все в порядке. В обоих случаях объекты новы. Я не мог определить проблему, копаясь в спящем коде, поэтому я создал sample project, чтобы продемонстрировать это (класс теста 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");
}
Редактировать 2016-08-08: Похоже, что когда новый объект с предопределенным идентификатором сохраняется, он получает два разных экземпляра createdBy и modifiedBy AuditorDetails, что вполне логично, если объект не будет фактически новым. Таким образом, совершенно новый объект сгенерированный получает как AuditorDetails одного и того же экземпляра, так и тот, у которого с установленным вручную идентификатором нет. Я проверил его, сохранив данные аудитора в компоненте AuditorAware, прежде чем возвращать его в AuditingHandler.