HQL: Fetch Join Collections from an Eager Table

I have four tables:

RootNode // Will return multiple root nodes SubNode // Will return one sub node per root node SubNodeChildren1 // Will return multiple for each sub node SubNodeChildren2 // Will return multiple for each sub node 

and a similar object structure:

 RootNode -> SubNode -> SubNodeChildren1 -> SubNodeChildren2 

I need one query that will return all RootNodes to a table with initialized child elements SubNode and SubNode . SubNode look, but SubNode children SubNode lazy SubNode out.

I know how to write a query that will LEFT OUTER JOIN FETCH immediate children of the table and initialize them accordingly. However, I have no idea how to grab the children of a table that is impatiently posted from a top-level table.

I tried something like:

 SELECT rn FROM RootNode AS rn LEFT OUTER JOIN FETCH rn.SubNode.SubNodeChildren1 

but it always gives me an error that the owner is not part of the SELECT.

Any help is greatly appreciated.

+7
sql hibernate hql
source share
2 answers

Here is the hibernate reference

The only reason we might need an alias is if we join recursively to select another collection.

It follows that your request should be rewritten as

 select distinct rn from RootNode rn left join fetch rn.subNode sn left join fetch sn.subNodeChildren 

You can either

disable default subNode fetch = FetchType.EAGER and just get what you really want using an HQL query. It (the HQL query) efficiently redefines external joins and lazy mapping file declarations for associations and collections (Hibernate reference documentation). This approach is supported by POJO in the action book.

or enable collection of SubNodeChildren as fetch = FetchType.EAGER

Hibernate is often asked questions (the link has been disabled (as far as I know), but I saved it until it disappeared)

In an MVC application, how can we guarantee that all proxies and lazy collections will be initialized when the view tries to access them?

One possible approach is to leave the session open (and the transaction without committing) when forwarded to the view. A session / transaction will be closed / committed after rendering the view, for example, a servlet filter (another example would be to use the ModelLifetime.discard () callback in Maverick). One of the difficulties with this approach is that the session / transaction is closed / rolled back if an exception occurs that displays the view.

...

Another approach is simply to force initialization of all necessary objects using Hibernate.initialize (). This is often more straightforward than it sounds.

+11
source share

To make the request work, I needed to do an INNER JOIN FETCH instead of a LEFT OUTER JOIN FETCH for an impatient object:

 SELECT rn FROM RootNode AS rn INNER JOIN FETCH rn.SubNode AS sn LEFT OUTER JOIN FETCH sn.SubNodeChildren1 LEFT OUTER JOIN FETCH sn.SubNodeChildren2 ... 

Honestly, I'm still not quite sure why it works with INNER JOIN FETCH vs a LEFT OUTER JOIN FETCH , but it definitely works just the way I need it.

+1
source share

All Articles