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

Vladimir Martinek vm at sykora.cz
Wed Jun 8 16:31:35 EDT 2016


Steve,

thank you very much. The test is extremely simple and as a programmer I 
thought those few lines of code would clear up any confusion.
It's perfectly OK to postpone the discussion and I will be very happy to 
continue once the problem is reproduced and understood.

Once again thank you for all your effort.

Vladimir


On 8.6.2016 16:08, Steve Ebersole wrote:
> Will do.  Was hoping to discuss.  But if I have to dig through your 
> test instead I certainly will, as soon as I get time.
>
> On Wed, Jun 8, 2016 at 2:29 AM Vladimir Martinek <vm at sykora.cz 
> <mailto:vm at sykora.cz>> wrote:
>
>     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 <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