Instantiate a proxy of the correct class for ManyToOne associated to an inheritance hierarchy

Description

Consider the following entities (getters, setters and PK omitted):

 

When loading a Container object, Hibernate creates an uninitialized proxy for the associated Food. The class of that proxy extends Food

So tests like container.getFood() instanceof Cheese will return false, even if the underlying instance might be of that type.

Since Hibernate 6.2 @Proxy(lazy = false) is deprecated. This was one way to get the correct java class, with the drawback that it effectively disabled lazy-loading.

 

Assuming that the Container table has a new food_type discriminator column next to the food_id FK column, Hibernate could use that new information to create a proxy of the correct class.

This would probably entail modifying the mapping, for instance adding a new @ManyToOneDiscriminatorColumn on the association:

An alternative would be that when the discriminator is part of an embedded id, Hibernate uses it create the correct class.

Another solution would be an user-supplied service (injected in the SessionFactory) responsible for locating the correct type, based on the ID.

This is a continuation of the discussion started here:

Activity

Show:

Guillaume Toison June 2, 2023 at 12:50 PM

Actually I do not have the permission to close it, so I let you be the judge.

The answers and insights are much appreciated, thank you!

Gavin King June 1, 2023 at 2:03 PM

As to whether you should close the issue, well, in principle the feature already exists. Now, in its current incarnation it comes with lots of limitations, in particular:

and for sure it would be nice to consider improving @Any, or perhaps somehow merging the idea a bit with regular association mappings, but I’m not sure your issue description really captures any of the work which is really required.

Gavin King June 1, 2023 at 1:39 PM
Edited

I mean if you want to just always load an association eagerly, that’s easy to do. I don’t really know why you were using @Proxy(lazy=FALSE) for that!

You can use @ManyToOne(fetch=EAGER) to tell Hibernate to load eagerly and eliminate the proxy, and then @Fetch(SELECT) or even better @Fetch(SUBSELECT) if you want to use a separate select instead of a join. And this is much better because it's more granular.

Guillaume Toison June 1, 2023 at 12:55 PM

I don’t want a pony, I want to keep using the donkey I already have

Basically I’m using @Proxy(lazy = false) to ensure that objects in an inheritance hierarchy have the right class, at the expense of relaxing the performance requirement (this breaks lazy loading).

In Hibernate 6.2 proxy loading seem to have changed because I get new errors, and these errors go away when I remove @Proxy(lazy = false) , I’m trying to pinpoint the problem but was not successful so far, for instance or

So I’ll keep trying to debug these errors, most probably the problem is in my code.

Thanks a lot for the answers; I’ll close this unless you tell me otherwise

Gavin King May 31, 2023 at 9:20 PM
Edited

Look, the more constraints you pile on, the less likely you are to find a solution.

It’s OK to ask for a pony, but hoping for a pony and a unicorn and a friendly dragon all at the same time might just be pushing it.

If I were you I would be asking myself which three of those requirements I might be able to relax and still make my program do what it needs to do.

Details

Assignee

Reporter

Priority

Created May 31, 2023 at 8:15 PM
Updated June 2, 2023 at 12:50 PM