[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