当持久化分离的实体时,Spring数据JPA审核失败
我已经使用Spring数据JPA AuditingEntityListener和AuditorAware bean设置了JPA审计。我想要的是,即使在具有预定义标识符的实体上,也能够持久化审计员的详细信息。 问题在于,当保留和刷新具有预定义id的JPA实体时,无法保留其审计员详细信息: 对象引用未保存的临时实例-在刷新之前保存临时实例:me.auditing.dao.AuditorDetails 有趣的是,当保存具有生成id的实体时,一切都很好。在这两种情况下,实体都是新的。我无法通过hibernate代码找出问题所在,因此我创建了一个测试类(测试类me.auditing.dao.AuditedEntityIntegrationTest)来演示这一点,它具有预定义和生成标识符的实体,应该进行审计 这些实体是:当持久化分离的实体时,Spring数据JPA审核失败,jpa,spring-boot,spring-data-jpa,auditing,Jpa,Spring Boot,Spring Data Jpa,Auditing,我已经使用Spring数据JPA AuditingEntityListener和AuditorAware bean设置了JPA审计。我想要的是,即使在具有预定义标识符的实体上,也能够持久化审计员的详细信息。 问题在于,当保留和刷新具有预定义id的JPA实体时,无法保留其审计员详细信息: 对象引用未保存的临时实例-在刷新之前保存临时实例:me.auditing.dao.AuditorDetails 有趣的是,当保存具有生成id的实体时,一切都很好。在这两种情况下,实体都是新的。我无法通过hiber
@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;
}
}
以及:
其中父类为:
@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;
而auditor getter实现是:
@Override
public AuditorDetails getCurrentAuditor() {
return new AuditorDetails()
.setId(null)
.setUserId("someUserId")
.setDivisionId("someDivisionId");
}
编辑2016-08-08:似乎当保存一个具有预定义id的新实体时,它会获得createdBy和modifiedBy AuditorDetails的两个不同实例,如果该实体实际上不是新的,这是非常合乎逻辑的。因此,一个生成了的全新实体将获取同一实例的两个AuditorDetails,而手动设置id的实体则不会。在返回给AuditingHandler之前,我通过在AuditorAware bean中保存auditor详细信息来测试它。好的,所以现在我能找到的唯一解决方案是在将AuditorDetails写入受审核实体之前实际保存AuditorDetails,如下所示:
@Override
@Transactional
public AuditorDetails getCurrentAuditor() {
AuditorDetails details = new AuditorDetails()
.setId(null)
.setUserId("someUserId")
.setDivisionId("someDivisionId");
return auditorDetailsRepository.save(details);
}
这并不是最优雅的解决方案,但目前它仍然有效
@Override
@Transactional
public AuditorDetails getCurrentAuditor() {
AuditorDetails details = new AuditorDetails()
.setId(null)
.setUserId("someUserId")
.setDivisionId("someDivisionId");
return auditorDetailsRepository.save(details);
}