Handling Proxy Types Correctly for Inheriting Stored Types


#1

Hello,

an application I am working on uses Hibernate quite extensively for storing complex data structures. A lot of lazy fetching is used for improved performance, which fundamentally works well. Now say I have three classes: ParentClass, ChildClass (which extends ParentClass) and ContainerClass. The ContainerClass has a lazily-fetched field foo of type ParentClass (e.g. a one-to-one relation with fetch set to lazy). I store an instance of ContainerClass with foo set to an instance of ChildClass.

If now retrieve that object of type ContainerClass from the database and call getFoo(). I get a HibernateProxy as result, as I am using lazy fetching. What I do not quite understand is why this HibernateProxy extends ParentClass as oppose to ChildClass. Sure, the field is of type ParentClass but the information that the actual value is of the more specific type ChildClass is present, so why not use this?

The fact that the proxy extends the more general parent class instead of the child class becomes problematic later, e.g. when trying to determine object types using instanceof. Say ChildClasss has an equals(Object o) method that does something like return o instanceof ChildClass && [...] then the equals method will return false whenever a HibernateProxy instance exists in place of a ChildClass instance.

Why does the proxy not inherit from ChildClass but ParentClass if a ChildClass was stored? What is the most elegant way to deal with this behavior and determine the most specific class a proxy actually proxies?

Thanks :slight_smile:!
j4r


#2

Without seeing the actual mappings and the code that you are executing, it’s hard to understand what you are talking about.

Try to build a replicating test case as it’s easier to understand your use case while debugging the problem.


#3

To demonstrate the issue I’ve created a relatively simple testcase using the same names as in my question (execute the test test()): https://github.com/jjbr/hibernate-test-case-templates/blob/proxyTypingIssue/orm/hibernate-orm-5/src/test/java/org/hibernate/bugs/JPAUnitTestCase.java#L33 - hope that makes the issue a bit clearer!


#4

The Proxy is always generated for the class provided at Java class level. That’s why the Proxy is for the ParentClass, not for a specific subclass.

@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
public ParentClass getParentClass() {
	return parentClass;
}

You might also be interested in the HHH-11280 issue which is about narrowing Proxies when using inheritance and associations.


#5

Right, of course it uses ParentClass because it cannot know that this particular instance is of type ChildClass without checking in the database => more overhead. Makes sense. Thanks also for the linked issue - I’ll try adding @Proxy(lazy = false) to relevant classes and see if I can work with that or if a more performant and involved approach is required. Thank you for your help!