I have a strange issue where hibernate does not create the expected entity type in a many to one relataionship. We have the following entities with subclass hierarchy (simplified):
@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
both entities are declared in the order
A2
A1
B2
B1
Now I create instances of A1 and B1 in the DB:
A1 a1 = new A1();
entityManager.persist(a1);
B1 b1 = new B1();
b1.setA(a1);
entityManager.persist(b1);
I can see the instances are saved to the DB correctly each have ID 1, DISCRIMINATOR is also 1, A_ID in B is also 1.
When I now try to get the B (in another hibernate session):
B b = entityManager.find(B.class, 1L);
I get the exception:
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
With debugging I found out that hibernate is creating the correct entity of type B1 and creates an incorrect entity of type A2 for the relationship to A. The correct type A1 is created if the order in the persistence.xml
is changed. It seems like hibernate doesn't take the DISCRIMINATOR column of A table into account in this case but always creates the first subtype declared in the configuration. How can this be fixed? Is there something wrong with the annotations?
(I also had the concrete implementation of method getA()
with its annotations in the supertype B at first, but this leads to similar problems.)