Hibernate Envers复合主键relatedId请求

Hibernate Envers composite primary key relatedId request

我使用 Hibernate Envers 进行审计,但遇到复合主键问题。基于相关属性,我有很多具有复合主键的实体。结构如下:

@Entity
@Audited
@Table(indexes = { @Index(columnList = "person_id"),
        @Index(columnList = "document_id") })
public class PersonDocument implements Serializable {

    private static final long serialVersionUID = 1L;

    @Id
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private Document document;

    @Id
    @ManyToOne(optional = false, fetch = FetchType.EAGER)
    private Person person;

关系没有双向注释。审计表中使用的主键是正确的,就像 envers 的文档描述的那样。

但现在我不想要所有与人有关的修改。以下内容:

final AuditQuery query = AuditReaderFactory.get(entityManager)
                .createQuery().forRevisionsOfEntity(PersonDocument.class, false, true)
                .add(AuditEntity.relatedId("person").eq("12"))
                .addOrder(AuditEntity.revisionNumber().desc());

然后我得到以下错误:

This criterion can only be used on a property that is a relation to another property.

如果我使用非复合主键,那么它运行没有问题,但是我得到了错误。有人有想法吗?将数据从复合主键迁移到多对多实体的额外主键并不容易。

我使用 Hibernate 版本 4.3.11

此致

这里的问题是 Envers 基本上不为 @Id 注释类型注册关系,这正是您 运行 进入此错误的原因。

不幸的是,Hibernate 4.3 不再维护,因此我们所做的任何错误修复目前都适用于 Hibernate 5.x,很可能只有 5.2.x.

也就是说,您可以使用一种解决方法来避免必须更改复合 ID 设置。这个想法是,您创建一个 属性 来隐藏复合 ID 键值,并使用隐藏的 属性 进行这些查询。

@Entity
@Audited
public class PersonDocument implements Serializable {
  @Id
  @ManyToOne(optional = false)
  private Document document; // lets assume this maps to document_id
  @Id
  @ManyToOne(optional = false)
  private Person person; // lets assume this maps to person_id

  // we'll shadow those properties now
  @Column(name = "document_id", nullable = false, insertable = false, updatable = false)
  private Integer documentId;

  @Column(name = "person_id", nullable = false, insertable = false, updatable = false)
  private Integer personId;
}

现在我们可以根据简单的属性进行查询,而不是使用 relatedId 方法:

reader.createQuery().forRevisionsOfEntity( PersonDocument.class, false, true )
  .add( AuditEntity.property( "personId" ).eq( 42 ) )
  .addOrder( AuditEntity.revisionNumber().desc() );

显然这不太理想,但您当然可以使用 @PostUpdate@PostPersist 之类的东西来保持各种阴影属性与其对象对应部分对齐。