How Hibernate determines type for proxy object

Viewed 126

I have a abstract @Entity with few concrete subclasses. For the sake of simplicity consider:

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "classType", discriminatorType = DiscriminatorType.STRING)
public abstract class Parent {
...
}

@Entity
@DiscriminatorValue("child1")
public class Child1 extends Parent {
...
}

@Entity
@DiscriminatorValue("child2")
public class Child2 extends Parent {
...
}

For loading of the class I have a repository which loads the abstract Parent:

interface ParentRepository extends JpaRepository<Parent, Long> { ... }

When I load the object I get obviously back Parent (at the time of loading I get just ID without knowing the type):

Parent parent = parentRepository.findById(1);

But underneath obviously it is the concrete type based on the discriminator value. So I should be allowed to down cast the parent above to Child1 or Child2. And this is usually the case. But under some circumstances which don't seem to be deterministic I get ClassCastException instead:

java.lang.ClassCastException: class ...Parent$HibernateProxy$MZu3Zm6v cannot be cast to class ...Child1 (...Parent$HibernateProxy$MZu3Zm6v and ...Child1 are in unnamed module of loader 'app')

To me it seems that sometimes hibernate decides to give me proxy instead of the real class and because the findById asks for Parent it gives me proxy for Parent type even though under the hood there is the real concrete class. So my concrete question based on the above would be:

  1. How does hibernate decide that sometimes it gives back concrete type (and downcast works as expected) and sometimes I get back HibernateProxy for Parent? Is it due to the object already being present in PersistentContext at the time of loading?

  2. How does Hibernate determine the underlying type for the HibernateProxy? Why it cannot make it proxy of the concrete type?

0 Answers
Related