Ho uno strano problema in cui l'ibernazione non crea il tipo di entità previsto in una relazione molti a uno. Abbiamo i seguenti entità gerarchia sottoclasse (semplificato):Sospensione durante la creazione di un sottotipo di entità errato nella relazione
@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
entrambe le entità sono dichiarate nell'ordine
A2
A1
B2
B1
Ora creare istanze di A1 e B1 nel DB:
A1 a1 = new A1();
entityManager.persist(a1);
B1 b1 = new B1();
b1.setA(a1);
entityManager.persist(b1);
Posso vedere le istanze sono salvate nel DB correttamente hanno ID 1, DISCRIMINATOR è anche 1, A_ID in B è anche 1.
Quando io ora cerco di ottenere la B (in un'altra sessione Hibernate):
B b = entityManager.find(B.class, 1L);
ottengo l'eccezione:
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
con il debug ho scoperto che Hibernate sta creando la giusta entità digitare B1 e crea un'entità non corretta di tipo A2 per la relazione con A. Il tipo corretto A1 viene creato se l'ordine nello persistence.xml
viene modificato. Sembra che l'ibernazione non tenga conto della colonna DISCRIMINATOR di una tabella in questo caso, ma crea sempre il primo sottotipo dichiarato nella configurazione. Come si puo aggiustare? C'è qualcosa di sbagliato nelle annotazioni?
(ho avuto anche l'attuazione concreta del metodo getA()
con le sue annotazioni nel supertipo B in un primo momento, ma questo porta a problemi simili.)
Grazie per la risposta. Ieri ho avuto la possibilità di testare questo e funziona nello scenario della domanda :) – Gandalf