我使用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
祝你好运
答案 0 :(得分:1)
这里的问题是Envers基本上没有注册@Id
注释类型的关系,这正是你遇到这个错误的原因。
不幸的是,Hibernate 4.3不再被维护,因此我们所做的任何错误修复此时都适用于Hibernate 5.x,很可能只是5.2.x。
也就是说,您可以使用一种解决方法来避免更改复合ID设置。我们的想法是创建一个隐藏复合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
之类的东西来保持各种阴影属性与它们的对象对应部分对齐。