Ich habe ein seltsames Problem, wo Hibernate den erwarteten Entitätstyp in einer Beziehung viele zu eins nicht erstellt. Wir haben die folgenden Organisationen, die mit der Unterklasse Hierarchie (vereinfacht):Hibernate erstellt falsche Entity Subtype in Beziehung
@Entity
@Table(name = "A")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 1)
public abstract class A {
@Id
...
public Long getId() { ... }
...
}
@Entity
@DiscriminatorValue("1")
public class A1 extends A {
...
}
@Entity
@DiscriminatorValue("2")
public class A2 extends A {
...
}
@Entity
@Table(name = "B")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "DISCRIMINATOR", discriminatorType = DiscriminatorType.STRING, length = 1)
public abstract class B<AClass extends A> {
protected AClass a;
@Id
...
public Long getId() { ... }
...
public abstract AClass getA();
public void setA(AClass a) { ... }
}
@Entity
@DiscriminatorValue("1")
public class B1 extends B<A1> {
...
@Override
@ManyToOne(fetch = EAGER)
@JoinColumn(name = "A_ID")
public A1 getA() { ... }
}
@Entity
@DiscriminatorValue("2")
public class B2 extends B<A2> {
...
@Override
@ManyToOne(fetch = EAGER)
@JoinColumn(name = "A_ID")
public A2 getA() { ... }
}
In persistence.xml
beide Einheiten in der Reihenfolge deklariert werden
A2
A1
B2
B1
Jetzt habe ich Instanzen von A1 und B1 in der DB zu erstellen:
A1 a1 = new A1();
entityManager.persist(a1);
B1 b1 = new B1();
b1.setA(a1);
entityManager.persist(b1);
Ich kann sehen, die Instanzen sind in der DB korrekt gespeichert haben jeweils ID 1, DISCRIMINATOR ist auch 1, A_ID in B ist auch 1.
Wenn ich jetzt versuchen, die B zu erhalten (in einer anderen Hibernate Session):
B b = entityManager.find(B.class, 1L);
bekomme ich die Ausnahme:
org.hibernate.PropertyAccessException: Exception occurred inside getter of B
Caused by: java.lang.ClassCastException: A2 cannot be cast to A1
at B1.getA(B1.java:61)
... 108 more
Mit Debugging Ich fand heraus, dass Hibernate ist die richtige Einheit zu schaffen, Geben Sie B1 ein, und erstellen Sie eine falsche Entität des Typs A2 für die Beziehung zu A. Der richtige Typ A1 wird erstellt, wenn die Reihenfolge in persistence.xml
geändert wird. Es scheint, dass Hibernate die DISCRIMINATOR-Spalte von A-Tabelle in diesem Fall nicht berücksichtigt, sondern immer den ersten in der Konfiguration deklarierten Subtyp erstellt. Wie kann das behoben werden? Stimmt etwas nicht mit den Anmerkungen?
(Ich hatte auch die konkrete Umsetzung der Methode getA()
mit seinen Anmerkungen in der Supertyp B auf den ersten, aber dies führt zu ähnlichen Problemen.)
Danke für Ihre Antwort. Gestern hatte ich die Möglichkeit dies zu testen und es funktioniert im Szenario der Frage :) – Gandalf