0

我使用Hibernate Envers进行审计,并且遇到了复合主键的问题。基于相关属性,我有许多具有复合主键的实体。构造如下:Hibernate Envers复合主键relatedId请求

@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

问候

回答

1

这里的问题是,Envers基本不注册@Id注解的类型,这也正是为什么你遇到了这个错误的关系。

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

也就是说,有一种解决方法可以用来避免必须更改您的composite-id设置。这个想法是,你创建一个属性,该属性会影响composite-id键值,并为这些查询使用shadowed属性。

@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以保持各种阴影属性与其对象的对应部分对齐。

+1

我在这里添加了一个与本次讨论相关的JIRA:https://hibernate.atlassian.net/browse/HHH-11748 – Naros

+1

对此的修复很简单。我们只需要能够对标识符执行第二遍就像我们对非标识符属性链接关联和组件属性一样。 – Naros