Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当持久化分离的实体时,Spring数据JPA审核失败_Jpa_Spring Boot_Spring Data Jpa_Auditing - Fatal编程技术网

当持久化分离的实体时,Spring数据JPA审核失败

当持久化分离的实体时,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

我已经使用Spring数据JPA AuditingEntityListener和AuditorAware bean设置了JPA审计。我想要的是,即使在具有预定义标识符的实体上,也能够持久化审计员的详细信息。 问题在于,当保留和刷新具有预定义id的JPA实体时,无法保留其审计员详细信息:

对象引用未保存的临时实例-在刷新之前保存临时实例:me.auditing.dao.AuditorDetails

有趣的是,当保存具有生成id的实体时,一切都很好。在这两种情况下,实体都是新的。我无法通过hibernate代码找出问题所在,因此我创建了一个测试类(测试类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;
    }
}
以及:

其中父类为:

@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);
}