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

时间:2016-08-08 11:34:28

标签: jpa spring-boot spring-data-jpa auditing

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

  

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

有趣的是,当保存具有生成ID的实体时 - 一切都很好。在这两种情况下,实体都是新的。我无法确定通过hibernate代码挖掘的问题所以我创建了一个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:似乎当保存具有预定义ID的新实体时,它会获得createdBy和modifiedBy AuditorDetails的两个不同实例,如果实体不能实现,则这是非常合理的实际上是新的。因此,生成的全新实体将获得相同实例的AuditorDetails,而具有手动设置ID的实体则不会。我在AuditorAware bean中保存审核员详细信息之前对其进行了测试,然后再将其返回到AuditingHandler。

1 个答案:

答案 0 :(得分:1)

好的,现在我能找到的唯一解决方案是在将AuditorDetails写入审计实体之前实际保留它:

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

这不是最优雅的解决方案,但它现在可以使用。