0

Ich benutze Hibernate Envers für Auditing und habe ein Problem mit zusammengesetzten Primärschlüssel. Ich habe viele bis viele Entitäten mit zusammengesetzten Primärschlüssel basierend auf den zugehörigen Eigenschaften. Das Konstrukt ist wie folgt:Hibernate Envers Composite Primärschlüssel relatedId Anfrage

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

Die Beziehung ist nicht bidirektional kommentiert. Der Primärschlüssel wird in den überprüften Tabellen korrekt verwendet, wie in der Enver-Dokumentation beschrieben.

Aber jetzt würde ich alle Revisionen, die sich auf die Person bezieht. Mit folgenden:

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

dann bekomme ich Fehler folgende:

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

Wenn ich einen nicht zusammengesetzten Primärschlüssel verwenden, dann läuft es ohne Probleme, aber mit ich den Fehler. Hat jemand eine Idee? Die Migration der Daten vom zusammengesetzten Primärschlüssel zu einem zusätzlichen Primärschlüssel für viele bis viele Entitäten ist nicht so einfach.

Ich benutze Hibernate Version 4.3.11

Mit freundlichen Grüßen

Antwort

1

Das Problem hierbei ist, dass Envers grundsätzlich nicht registriert Beziehungen für @Id kommentierte Typen, die genau ist, warum Sie in diesem Fehler ausgeführt.

Leider wird Hibernate 4.3 nicht mehr gepflegt, daher ist ein Bugfix, der an diesem Punkt auf Hibernate 5.x angewendet werden kann, höchstwahrscheinlich nur 5.2.x.

Wie gesagt, es gibt eine Problemumgehung, die Sie verwenden können, um zu vermeiden, dass Sie Ihre Composite-ID-Konfiguration ändern müssen. Die Idee ist, dass Sie eine Eigenschaft erstellen, die die Schlüsselwerte der zusammengesetzten ID schattiert und die schattierte Eigenschaft für diese Abfragen verwendet.

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

Jetzt anstatt die relatedId Ansatz können wir auf einfache Eigenschaften Abfrage basiert:

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

Offensichtlich ist dies weniger als ideal, aber man kann sicherlich Dinge verwenden, wie @PostUpdate und @PostPersist, um Behalten Sie die verschiedenen schattierten Eigenschaften mit ihren Objektgegenstücken ausgerichtet.

+1

Ich fügte eine JIRA zu dieser Diskussion hier hinzu: https://hibernate.atlassian.net/browse/HHH-11748 – Naros

+1

Die Lösung dafür erwies sich als recht einfach. Wir müssen nur in der Lage sein, einen zweiten Durchlauf von Bezeichnern durchzuführen, ähnlich wie wir es für Nicht-Bezeichner-Eigenschaften tun, um Verknüpfungen und Komponenteneigenschaften zu verknüpfen. – Naros

Verwandte Themen