I have a strange problem where hibernation does not create the expected entity type in many respects between relataionship. We have the following objects with a 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 order
A2 A1 B2 B1
Now I create instances of A1 and B1 in the database:
A1 a1 = new A1(); entityManager.persist(a1); B1 b1 = new B1(); b1.setA(a1); entityManager.persist(b1);
I see that the instances are saved in the database correctly, each of them has the identifier 1, DISCRIMINATOR is also 1, A_ID in B is also 1.
When I'm trying to get B now (in another hibernation session):
B b = entityManager.find(B.class, 1L);
I get an 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 discovered that hibernate was creating the correct object of type B1 and creating the wrong object of type A2 to relate to A. The correct type A1 is created if the order in persistence.xml changed. It seems that hibernate does not account for the DISCRIMINATOR column of table A in this case, but always creates the first subtype declared in the configuration. How can this be fixed? Is there something wrong with annotations?
(I also had a specific implementation of the getA() method with its annotations in supertype B at first, but this leads to similar problems.)
java hibernate jpa discriminator
Gandalf
source share