[hibernate-dev] Relations are not loaded when using Fetch Profiles

Vladimir Martinek vm at sykora.cz
Wed Jun 8 03:28:51 EDT 2016


MetamodelGraphWalker line 144. My relation is in 
MetamodelGraphWalker.visitedAssociationKeys, so it gets skipped and thus 
not make it in the final big SQL SELECT.

Why don't you take a look at the test case I provided - just run it and 
see the LazyInitializationException error, it will all be instantly 
clear.  I am talking about LAZY relations in combination with 
FetchProfile using FetchMode.JOIN. Please disregard EAGER (for now, we 
may come to that later once we agree on what is the problem :)

We prefer to have all relations LAZY on our project (performance 
reasons) and use FetchProfiles. The actual FetchMode (whether it is 
JOIN, SELECT) does not matter to us, all we need is the relations to be 
loaded in single EntityManager.find call. Unfortunately the only 
FetchMode implemented now is JOIN and that one has this unpleasant bug 
in it.

Thank you

Vladimir


On 06/07/2016 04:01 PM, Steve Ebersole wrote:
> MetamodelGraphWalker does not consider them cycles.  Where do you see 
> MetamodelGraphWalker making that decision? MetamodelGraphWalker simply 
> walks your model mappings.  It delegates to pluggable strategies.  So 
> I assume you really mean one of the AssociationVisitationStrategy 
> implementations is considering them cycles.  And even then I am not so 
> sure that is what happens...
>
> So to be clear we are talking about 2 different EAGER fetch strategies 
> here: join and select.
>
> For join, we'd build one big SQL SELECT joining the relations 
> together. You can see this by switching your associations from lazy to 
> all being eager and specifying join fetching.
>
> For select, we'd build one SQL SELECT for the root entity being loaded 
> (and any join fetched relations).  From there, any select-fetched 
> relations would be loaded individually by separate select (that's kind 
> of the definition of N+1).
>
>
>
> On Tue, Jun 7, 2016 at 8:50 AM Vladimir Martinek <vm at sykora.cz 
> <mailto:vm at sykora.cz>> wrote:
>
>     Hello,
>
>     actually I would like to learn how the FetchMode.JOIN is supposed
>     to work in case of cycles (not really cycles but
>     MetamodelGraphWalker considers them cycles).
>
>     Check the test case please - it gets LazyInitializationException
>     on a relation despite that relation being marked as JOIN FETCH in
>     the fetch profile.
>
>     How is this intended to work? Is it a problem of
>     MetamodelGraphWalker and its cycle detection? Or is it planned
>     limitation of FetchMode.JOIN?
>
>     I can help to fix this, but in order to do that I need to know how
>     this is expected to work.
>
>     Please disregard EAGER. I only mentioned FetchType.EAGER because I
>     noticed it can cope with the same cyclic relations - and yes, you
>     are right, those are fetched in subsequent selects. But we can't
>     use EAGER (performance reasons).
>
>     Thank you
>
>     Vladimir
>
>
>
>
>
>     On 06/07/2016 03:05 PM, Steve Ebersole wrote:
>>     There is a huge difference in join-fetch and what we detail for
>>     "EAGER".  Join-fetch is also an eager fetch.  There are 2 pieces
>>     of information in regards to fetching: when, how?
>>
>>     EAGER merely describes when: now.
>>
>>     What you describe as "EAGER" is really a N+1 fetch.  So the
>>     relation is fetched immediately, but as "subsequent select".  A
>>     join-fetch is still EAGER, but now the relation is fetch via join
>>     in the initial query.  Very different behavior.
>>
>>     On Tue, Jun 7, 2016 at 4:38 AM Vladimir Martinek <vm at sykora.cz
>>     <mailto:vm at sykora.cz>> wrote:
>>
>>         HHH-10745, runnable test case attached to that issue
>>         (org.hibernate.test.fetchprofiles.cycle.tar.gz).
>>
>>         Thank you
>>
>>         Vladimir
>>
>>
>>
>>         On 06/07/2016 06:00 AM, Gail Badner wrote:
>>         > Please create a Jira issue and attach a runnable test case.
>>         > Thanks,
>>         > Gail
>>         >
>>         > On Thu, Jun 2, 2016 at 5:45 AM, Vladimir Martinek
>>         <vm at sykora.cz <mailto:vm at sykora.cz>
>>         > <mailto:vm at sykora.cz <mailto:vm at sykora.cz>>> wrote:
>>         >
>>         >     Fetch profiles fail to load certain relations because
>>         of invalid cycle
>>         >     detection in MetamodelGraphWalker. Below is an example.
>>         >
>>         >     I have compared the behaviour of Fetch Profiles and
>>         standard EAGER
>>         >     relations (EAGER does not suffer from this problem). The
>>         >     MetamodelGraphWalker graph walker produces the same
>>         results, the
>>         >     SQL is
>>         >     the same (missing relation).
>>         >
>>         >     With EAGER the relation is loaded in second pass, via
>>         >     SessionImpl.internalLoad(). There it is decided what
>>         LoadType is
>>         >     used -
>>         >     for eager it uses INTERNAL_LOAD_EAGER, for lazy
>>         INTERNAL_LOAD_LAZY. It
>>         >     does not take into account the fetch profiles here!
>>         >
>>         >     The last place I can get hold of fetch profiles in in
>>         >     AbstractLoadPlanBasedEntityLoader line 82. After that
>>         the fetch
>>         >     profile
>>         >     information is lost, never making it anywhere near to
>>         >     SessionImpl.internalLoad().
>>         >
>>         >     I would like to implement this, but to do that, I need
>>         someone to
>>         >     point
>>         >     me in the right direction. Most of all I need answers
>>         to following
>>         >     questions:
>>         >
>>         >     1) Is it right to assume the fetch profiles should be
>>         evaluated in
>>         >     SessionImpl.internalLoad() and appropriate LoadType
>>         used when
>>         >     detected a
>>         >     relation affected by a fetch profile?
>>         >     2) If so, what is the intended way of getting the fetch
>>         profile
>>         >     information to SessionImpl.internalLoad()?
>>         >
>>         >     Also, a colleague of mine attempted to implement
>>         FetchType.SELECT
>>         >     fetch
>>         >     strategy and ended up with precisely the same problem.
>>         I believe
>>         >     solving
>>         >     my issue would pave way for quick FetchType.SELECT
>>         implementation
>>         >     (which
>>         >     we could also use on our project).
>>         >
>>         >
>>         >     Thank you
>>         >
>>         >     Vladimir Martinek
>>         >
>>         >
>>         >     Example:
>>         >
>>         >     Have 5 entities - Start, Via1, Via2, Mid and Finish
>>         with following
>>         >     relations (all LAZY):
>>         >
>>         >     Start n:1 Via1 n:1 Mid n:1 Finish
>>         >     Start n:1 Via2 n:1 Mid n:1 Finish
>>         >
>>         >     Now, trying to use Fetch Profiles to load Start entity
>>         and all of its
>>         >     relations. I would expect Hibernate to execute
>>         following SQL select:
>>         >
>>         >     SELECT * FROM Start s
>>         >     LEFT OUTER JOIN Via1 v1 (path Start-Via1)
>>         >     LEFT OUTER JOIN Mid
>>         >     JOIN Finish
>>         >
>>         >     LEFT OUTER JOIN Via2 (path Start-Via2)
>>         >     LEFT OUTER JOIN Mid
>>         >     JOIN Finish
>>         >
>>         >     Unfortunately, ii ompletely omits the second join from
>>         Mid to Finish,
>>         >     what I am getting is:
>>         >
>>         >     SELECT * FROM Start s
>>         >     LEFT OUTER JOIN Via1 v1 (path Start-Via1)
>>         >     LEFT OUTER JOIN Mid
>>         >     JOIN Finish
>>         >
>>         >     LEFT OUTER JOIN Via2 (path Start-Via2)
>>         >     LEFT OUTER JOIN Mid
>>         >
>>         >     I dug deeper into this and found cycle detection in
>>         >     MetamodelGraphWalker, line 144. Basically, when
>>         MetamodelGraphWalker
>>         >     detects a relation that has already been visited, it
>>         considers it a
>>         >     cycle. But in my case it is not a cycle - I just came
>>         to the same
>>         >     relation twice using two different paths.
>>         >
>>         >
>>         >  _______________________________________________
>>         >     hibernate-dev mailing list
>>         > hibernate-dev at lists.jboss.org
>>         <mailto:hibernate-dev at lists.jboss.org>
>>         <mailto:hibernate-dev at lists.jboss.org
>>         <mailto:hibernate-dev at lists.jboss.org>>
>>         > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>         >
>>         >
>>
>>
>>         --
>>
>>         *Ing. Vladimír Martinek*
>>         Programmer
>>
>>         T: +420 723 908 968
>>         @: vm at sykora.cz <mailto:vm at sykora.cz>
>>
>>         Sykora Data Center s.r.o.
>>         28. října 1512/123, 702 00 Ostrava
>>         www.sykora.cz <http://www.sykora.cz>
>>
>>         _______________________________________________
>>         hibernate-dev mailing list
>>         hibernate-dev at lists.jboss.org
>>         <mailto:hibernate-dev at lists.jboss.org>
>>         https://lists.jboss.org/mailman/listinfo/hibernate-dev
>>
>
>
>     -- 
>
>     *Ing. Vladimír Martinek*
>     Programmer
>
>     T: +420 723 908 968
>     @: vm at sykora.cz <mailto:vm at sykora.cz>
>
>     Sykora Data Center s.r.o.
>     28. října 1512/123, 702 00 Ostrava
>     www.sykora.cz <http://www.sykora.cz>
>


-- 

*Ing. Vladimír Martinek*
Programmer

T: +420 723 908 968
@: vm at sykora.cz

Sykora Data Center s.r.o.
28. října 1512/123, 702 00 Ostrava
www.sykora.cz



More information about the hibernate-dev mailing list