Home » Modeling » EMF "Technology" (Ecore Tools, EMFatic, etc) » Teneo: Objects are not added to resource.contents if fetch="subselect" for collection
| |
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65619 is a reply to message #65598] |
Wed, 27 December 2006 13:10 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Hi Martin
I suppose that these details help you to understand problem:
This is stack trace:
Thread [main] (Suspended (breakpoint at line 366 in
AbstractPersistentCollection))
PersistentBag(AbstractPersistentCollection).setInitialized() line: 366
PersistentBag(AbstractPersistentCollection).afterInitialize( ) line: 319
PersistentBag(AbstractPersistentCollection).endRead() line: 315
CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
CollectionPersister, EntityMode) line: 183
CollectionLoadContext.endLoadingCollections(CollectionPersis ter, List,
EntityMode) line: 268
CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
Object, SessionImplementor) line: 249
SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
SessionImplementor, CollectionPersister) line: 866
SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
Object, SessionImplementor, boolean) line: 853
SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
QueryParameters, boolean) line: 717
SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
QueryParameters, boolean) line: 224
SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
Serializable[], Object[], Type[], Map, Type) line: 1990
SubselectOneToManyLoader.initialize(Serializable, SessionImplementor)
line: 58
OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
SessionImplementor) line: 565
DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
line: 60
SessionImpl.initializeCollection(PersistentCollection, boolean) line: 1716
PersistentBag(AbstractPersistentCollection).initialize(boole an) line: 344
PersistentBag(AbstractPersistentCollection).read() line: 86
PersistentBag.toArray() line: 257
HibernatePersistableEList.doLoad() line: 106
HibernatePersistableEList(PersistableEList).load() line: 187
HibernatePersistableEList(PersistableEList).delegateSize() line: 395
HibernatePersistableEList(DelegatingEList).size() line: 214
DelegatingEList$EIterator.hasNext() line: 1000
DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
line: 339
DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
line: 380
As you see activity begins with: HibernatePersistableEList.doLoad()
line: 106
and PersistentBag is marked as initialized BUT: request was passed to
EXACTLY ONE HibernatePersistableEList - so after PersistentBag
corresponding to THIS HibernatePersistableEList was loaded all objects
contained in PersistentBag are added to resource - it's OK.
PROBLEM:
Actually in my example THREE PersistentBag were loaded - cause three
object with such lazy collections are already loaded - try to
investigate org.hibernate.engine.endLoadingCollections() method - it has
following code:
final int count = (resultSetCollections == null) ? 0 :
resultSetCollections.size();
if ( log.isDebugEnabled() ) {
log.debug( count + " collections were found in result set for role: "
+ persister.getRole() );
}
//now finish them
for ( int i = 0; i < count; i++ ) {
LoadingCollectionEntry lce = (LoadingCollectionEntry)
resultSetCollections.get(i);
endLoadingCollection(lce, persister, em);
}
if ( log.isDebugEnabled() ) {
log.debug( count + " collections initialized for role: " +
persister.getRole() );
}
In my example count = 3. So THREE PersistentBags were loaded - it
happened because my association has fetch="subselect".
So THREE PersistentBags were were marked as initialized but ONLY object
from ONE OF THEM were added to contents of resource.
Why other were not added?
Answer is simple:
Method doLoad() was not called for two other HibernatePersistableEList.
Adding objects to resource.contents() is in this method. Why was notthis
method called to two other list? Cause it is called only if isLoaded()
returns false.
BUT HOW is this method implemented for HibernatePersistableEList?
public boolean isLoaded() {
if (delegate instanceof AbstractPersistentCollection) {
if (((AbstractPersistentCollection) delegate).wasInitialized()) {
setIsLoaded(true);
// log.debug("Persistentlist already initialized, probably eagerly
loaded: " + getLogString());
}
}
return super.isLoaded();
}
So let me describe full chain of events:
There are THREE objects with lazy not loaded collections with
fetch="subselect". When one of HibernatePersistableELists is asked for
collection it force hibernate to load this collection via
Object[] objs = delegate.toArray(); // this forces the load
and adds objects to resource.
BUT during forcing of loading one delegate two other delegates were
loaded too - they were marked as initialized. So two other
HibernatePersistableELists will return isLoaded() = true because:
public boolean isLoaded() {
if (delegate instanceof AbstractPersistentCollection) {
if (((AbstractPersistentCollection) delegate).wasInitialized()) {
setIsLoaded(true);
// log.debug("Persistentlist already initialized, probably eagerly
loaded: " + getLogString());
}
}
return super.isLoaded();
}
So Teneo looses the moment when delegate is really initialized.
This happens when fetch="subselect". Details of how fetch="subselect"
works are in hibernate docs.
My proposals:
You can override setIsLoaded() in HibernatePersistableELists and check
that objects are added - then isLoaded needs to be implemented like:
public boolean isLoaded() {
if (isLoaded){
return true;
}
if (delegate instanceof AbstractPersistentCollection) {
if (((AbstractPersistentCollection) delegate).wasInitialized()) {
setIsLoaded(true);
// log.debug("Persistentlist already initialized, probably eagerly
loaded: " + getLogString());
}
}
return super.isLoaded();
}
Feel free to ask me for more details if my answer is not enough.
Ilya
Martin Taal wrote:
> I do not fully understand what happens here. Can you describe the
> case/example in which this occurs (automatically loading other such
> collections)? The hibernate behavior as you describe it is unfamiliar to
> me.
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> When I use HibernateResource with loading strategy addToContents then
>> all is OK until I have created association with fetch="subselect".
>> Sometimes objects that are inside these lazy collections are loaded
>> they are not added to resource.
>>
>> As far as I understand it happens when I ask some objects from ONE
>> such collection BUT if there are any other such collections that are
>> not loaded Hibernate can load all such collections. And fact of
>> loading of other collections are not caught by Teneo.
>>
>> Is this a bug?
>>
>> Thanks
>>
>> Ilya
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65639 is a reply to message #65619] |
Wed, 27 December 2006 13:13 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Sorry - I misprinted method name where ALL INTERESTING happens:
org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
instead of org.hibernate.engine.endLoadingCollections()
Ilya
Ilya Klyuchnikov wrote:
> Hi Martin
>
> I suppose that these details help you to understand problem:
>
> This is stack trace:
>
> Thread [main] (Suspended (breakpoint at line 366 in
> AbstractPersistentCollection))
> PersistentBag(AbstractPersistentCollection).setInitialized() line:
> 366
> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
> 319
> PersistentBag(AbstractPersistentCollection).endRead() line: 315
> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
> CollectionPersister, EntityMode) line: 183
> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
> List, EntityMode) line: 268
> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
> Object, SessionImplementor) line: 249
> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
> SessionImplementor, CollectionPersister) line: 866
> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
> Object, SessionImplementor, boolean) line: 853
> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
> QueryParameters, boolean) line: 717
> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
> QueryParameters, boolean) line: 224
> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
> Serializable[], Object[], Type[], Map, Type) line: 1990
> SubselectOneToManyLoader.initialize(Serializable,
> SessionImplementor) line: 58
> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
> SessionImplementor) line: 565
> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
> line: 60
> SessionImpl.initializeCollection(PersistentCollection, boolean)
> line: 1716
> PersistentBag(AbstractPersistentCollection).initialize(boole an)
> line: 344
> PersistentBag(AbstractPersistentCollection).read() line: 86
> PersistentBag.toArray() line: 257
> HibernatePersistableEList.doLoad() line: 106
> HibernatePersistableEList(PersistableEList).load() line: 187
> HibernatePersistableEList(PersistableEList).delegateSize() line: 395
> HibernatePersistableEList(DelegatingEList).size() line: 214
> DelegatingEList$EIterator.hasNext() line: 1000
> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
> line: 339
> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
> line: 380
>
> As you see activity begins with: HibernatePersistableEList.doLoad()
> line: 106
>
> and PersistentBag is marked as initialized BUT: request was passed to
> EXACTLY ONE HibernatePersistableEList - so after PersistentBag
> corresponding to THIS HibernatePersistableEList was loaded all objects
> contained in PersistentBag are added to resource - it's OK.
>
> PROBLEM:
>
> Actually in my example THREE PersistentBag were loaded - cause three
> object with such lazy collections are already loaded - try to
> investigate org.hibernate.engine.endLoadingCollections() method - it has
> following code:
>
> final int count = (resultSetCollections == null) ? 0 :
> resultSetCollections.size();
>
> if ( log.isDebugEnabled() ) {
> log.debug( count + " collections were found in result set
> for role: " + persister.getRole() );
> }
>
> //now finish them
> for ( int i = 0; i < count; i++ ) {
> LoadingCollectionEntry lce = (LoadingCollectionEntry)
> resultSetCollections.get(i);
> endLoadingCollection(lce, persister, em);
> }
>
> if ( log.isDebugEnabled() ) {
> log.debug( count + " collections initialized for role: " +
> persister.getRole() );
> }
>
> In my example count = 3. So THREE PersistentBags were loaded - it
> happened because my association has fetch="subselect".
>
> So THREE PersistentBags were were marked as initialized but ONLY object
> from ONE OF THEM were added to contents of resource.
>
> Why other were not added?
>
> Answer is simple:
> Method doLoad() was not called for two other HibernatePersistableEList.
> Adding objects to resource.contents() is in this method. Why was notthis
> method called to two other list? Cause it is called only if isLoaded()
> returns false.
>
> BUT HOW is this method implemented for HibernatePersistableEList?
>
> public boolean isLoaded() {
> if (delegate instanceof AbstractPersistentCollection) {
> if (((AbstractPersistentCollection)
> delegate).wasInitialized()) {
> setIsLoaded(true);
> // log.debug("Persistentlist already initialized,
> probably eagerly loaded: " + getLogString());
> }
> }
> return super.isLoaded();
> }
>
> So let me describe full chain of events:
>
> There are THREE objects with lazy not loaded collections with
> fetch="subselect". When one of HibernatePersistableELists is asked for
> collection it force hibernate to load this collection via
>
> Object[] objs = delegate.toArray(); // this forces the load
>
> and adds objects to resource.
>
> BUT during forcing of loading one delegate two other delegates were
> loaded too - they were marked as initialized. So two other
> HibernatePersistableELists will return isLoaded() = true because:
>
> public boolean isLoaded() {
> if (delegate instanceof AbstractPersistentCollection) {
> if (((AbstractPersistentCollection)
> delegate).wasInitialized()) {
> setIsLoaded(true);
> // log.debug("Persistentlist already initialized,
> probably eagerly loaded: " + getLogString());
> }
> }
> return super.isLoaded();
> }
>
> So Teneo looses the moment when delegate is really initialized.
>
> This happens when fetch="subselect". Details of how fetch="subselect"
> works are in hibernate docs.
>
> My proposals:
> You can override setIsLoaded() in HibernatePersistableELists and check
> that objects are added - then isLoaded needs to be implemented like:
>
> public boolean isLoaded() {
> if (isLoaded){
> return true;
> }
> if (delegate instanceof AbstractPersistentCollection) {
> if (((AbstractPersistentCollection)
> delegate).wasInitialized()) {
> setIsLoaded(true);
> // log.debug("Persistentlist already initialized,
> probably eagerly loaded: " + getLogString());
> }
> }
> return super.isLoaded();
> }
>
> Feel free to ask me for more details if my answer is not enough.
>
> Ilya
>
> Martin Taal wrote:
>> I do not fully understand what happens here. Can you describe the
>> case/example in which this occurs (automatically loading other such
>> collections)? The hibernate behavior as you describe it is unfamiliar
>> to me.
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> When I use HibernateResource with loading strategy addToContents then
>>> all is OK until I have created association with fetch="subselect".
>>> Sometimes objects that are inside these lazy collections are loaded
>>> they are not added to resource.
>>>
>>> As far as I understand it happens when I ask some objects from ONE
>>> such collection BUT if there are any other such collections that are
>>> not loaded Hibernate can load all such collections. And fact of
>>> loading of other collections are not caught by Teneo.
>>>
>>> Is this a bug?
>>>
>>> Thanks
>>>
>>> Ilya
>>
>>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65661 is a reply to message #65639] |
Wed, 27 December 2006 13:48 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Hi Ilya,
Yes the solution is in the isLoaded method. If the underlying hibernate collection is already
loaded/initialized while isLoaded=false then the children need to be added to the resource (calling
doLoad with some extra handling should work).
Are the automatically loaded collections eager or lazy?
gr. Martin
Ilya Klyuchnikov wrote:
> Sorry - I misprinted method name where ALL INTERESTING happens:
>
> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
> instead of org.hibernate.engine.endLoadingCollections()
>
> Ilya
>
> Ilya Klyuchnikov wrote:
>> Hi Martin
>>
>> I suppose that these details help you to understand problem:
>>
>> This is stack trace:
>>
>> Thread [main] (Suspended (breakpoint at line 366 in
>> AbstractPersistentCollection))
>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>> 366
>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>> 319 PersistentBag(AbstractPersistentCollection).endRead() line:
>> 315
>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>> CollectionPersister, EntityMode) line: 183
>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter, List,
>> EntityMode) line: 268
>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>> Object, SessionImplementor) line: 249
>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>> SessionImplementor, CollectionPersister) line: 866
>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>> Object, SessionImplementor, boolean) line: 853
>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>> QueryParameters, boolean) line: 717
>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>> QueryParameters, boolean) line: 224
>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>> Serializable[], Object[], Type[], Map, Type) line: 1990
>> SubselectOneToManyLoader.initialize(Serializable, SessionImplementor)
>> line: 58
>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>> SessionImplementor) line: 565
>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>> line: 60 SessionImpl.initializeCollection(PersistentCollection,
>> boolean) line: 1716
>> PersistentBag(AbstractPersistentCollection).initialize(boole an) line:
>> 344 PersistentBag(AbstractPersistentCollection).read() line:
>> 86 PersistentBag.toArray() line: 257
>> HibernatePersistableEList.doLoad() line: 106
>> HibernatePersistableEList(PersistableEList).load() line: 187
>> HibernatePersistableEList(PersistableEList).delegateSize() line: 395
>> HibernatePersistableEList(DelegatingEList).size() line: 214
>> DelegatingEList$EIterator.hasNext() line: 1000
>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>> line: 339
>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>> line: 380 As you see activity begins with:
>> HibernatePersistableEList.doLoad() line: 106
>>
>> and PersistentBag is marked as initialized BUT: request was passed to
>> EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>> corresponding to THIS HibernatePersistableEList was loaded all objects
>> contained in PersistentBag are added to resource - it's OK.
>>
>> PROBLEM:
>>
>> Actually in my example THREE PersistentBag were loaded - cause three
>> object with such lazy collections are already loaded - try to
>> investigate org.hibernate.engine.endLoadingCollections() method - it
>> has following code:
>>
>> final int count = (resultSetCollections == null) ? 0 :
>> resultSetCollections.size();
>>
>> if ( log.isDebugEnabled() ) {
>> log.debug( count + " collections were found in result set
>> for role: " + persister.getRole() );
>> }
>>
>> //now finish them
>> for ( int i = 0; i < count; i++ ) {
>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>> resultSetCollections.get(i);
>> endLoadingCollection(lce, persister, em);
>> }
>>
>> if ( log.isDebugEnabled() ) {
>> log.debug( count + " collections initialized for role: " +
>> persister.getRole() );
>> }
>>
>> In my example count = 3. So THREE PersistentBags were loaded - it
>> happened because my association has fetch="subselect".
>>
>> So THREE PersistentBags were were marked as initialized but ONLY
>> object from ONE OF THEM were added to contents of resource.
>>
>> Why other were not added?
>>
>> Answer is simple:
>> Method doLoad() was not called for two other
>> HibernatePersistableEList. Adding objects to resource.contents() is in
>> this method. Why was notthis method called to two other list? Cause it
>> is called only if isLoaded() returns false.
>>
>> BUT HOW is this method implemented for HibernatePersistableEList?
>>
>> public boolean isLoaded() {
>> if (delegate instanceof AbstractPersistentCollection) {
>> if (((AbstractPersistentCollection)
>> delegate).wasInitialized()) {
>> setIsLoaded(true);
>> // log.debug("Persistentlist already initialized,
>> probably eagerly loaded: " + getLogString());
>> }
>> }
>> return super.isLoaded();
>> }
>>
>> So let me describe full chain of events:
>>
>> There are THREE objects with lazy not loaded collections with
>> fetch="subselect". When one of HibernatePersistableELists is asked for
>> collection it force hibernate to load this collection via
>>
>> Object[] objs = delegate.toArray(); // this forces the load
>>
>> and adds objects to resource.
>>
>> BUT during forcing of loading one delegate two other delegates were
>> loaded too - they were marked as initialized. So two other
>> HibernatePersistableELists will return isLoaded() = true because:
>>
>> public boolean isLoaded() {
>> if (delegate instanceof AbstractPersistentCollection) {
>> if (((AbstractPersistentCollection)
>> delegate).wasInitialized()) {
>> setIsLoaded(true);
>> // log.debug("Persistentlist already initialized,
>> probably eagerly loaded: " + getLogString());
>> }
>> }
>> return super.isLoaded();
>> }
>>
>> So Teneo looses the moment when delegate is really initialized.
>>
>> This happens when fetch="subselect". Details of how fetch="subselect"
>> works are in hibernate docs.
>>
>> My proposals:
>> You can override setIsLoaded() in HibernatePersistableELists and check
>> that objects are added - then isLoaded needs to be implemented like:
>>
>> public boolean isLoaded() {
>> if (isLoaded){
>> return true;
>> }
>> if (delegate instanceof AbstractPersistentCollection) {
>> if (((AbstractPersistentCollection)
>> delegate).wasInitialized()) {
>> setIsLoaded(true);
>> // log.debug("Persistentlist already initialized,
>> probably eagerly loaded: " + getLogString());
>> }
>> }
>> return super.isLoaded();
>> }
>>
>> Feel free to ask me for more details if my answer is not enough.
>>
>> Ilya
>>
>> Martin Taal wrote:
>>> I do not fully understand what happens here. Can you describe the
>>> case/example in which this occurs (automatically loading other such
>>> collections)? The hibernate behavior as you describe it is unfamiliar
>>> to me.
>>>
>>> gr. Martin
>>>
>>> Ilya Klyuchnikov wrote:
>>>> When I use HibernateResource with loading strategy addToContents
>>>> then all is OK until I have created association with fetch="subselect".
>>>> Sometimes objects that are inside these lazy collections are loaded
>>>> they are not added to resource.
>>>>
>>>> As far as I understand it happens when I ask some objects from ONE
>>>> such collection BUT if there are any other such collections that are
>>>> not loaded Hibernate can load all such collections. And fact of
>>>> loading of other collections are not caught by Teneo.
>>>>
>>>> Is this a bug?
>>>>
>>>> Thanks
>>>>
>>>> Ilya
>>>
>>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65683 is a reply to message #65661] |
Wed, 27 December 2006 13:54 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
In my example lazy="true".
BTW, if there are collections with lazy="false" then during resource
loading objects in such collections are not added to resource.
Martin Taal wrote:
> Hi Ilya,
> Yes the solution is in the isLoaded method. If the underlying hibernate
> collection is already loaded/initialized while isLoaded=false then the
> children need to be added to the resource (calling doLoad with some
> extra handling should work).
>
> Are the automatically loaded collections eager or lazy?
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>
>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>> instead of org.hibernate.engine.endLoadingCollections()
>>
>> Ilya
>>
>> Ilya Klyuchnikov wrote:
>>> Hi Martin
>>>
>>> I suppose that these details help you to understand problem:
>>>
>>> This is stack trace:
>>>
>>> Thread [main] (Suspended (breakpoint at line 366 in
>>> AbstractPersistentCollection))
>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>> 366
>>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>>> 319 PersistentBag(AbstractPersistentCollection).endRead() line:
>>> 315
>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>> CollectionPersister, EntityMode) line: 183
>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>> List, EntityMode) line: 268
>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>> Object, SessionImplementor) line: 249
>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>> SessionImplementor, CollectionPersister) line: 866
>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>> Object, SessionImplementor, boolean) line: 853
>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>> QueryParameters, boolean) line: 717
>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>> QueryParameters, boolean) line: 224
>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>> SubselectOneToManyLoader.initialize(Serializable, SessionImplementor)
>>> line: 58
>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>> SessionImplementor) line: 565
>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>> line: 60 SessionImpl.initializeCollection(PersistentCollection,
>>> boolean) line: 1716
>>> PersistentBag(AbstractPersistentCollection).initialize(boole an) line:
>>> 344 PersistentBag(AbstractPersistentCollection).read() line:
>>> 86 PersistentBag.toArray() line: 257
>>> HibernatePersistableEList.doLoad() line: 106
>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>> line: 339
>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>> line: 380 As you see activity begins with:
>>> HibernatePersistableEList.doLoad() line: 106
>>>
>>> and PersistentBag is marked as initialized BUT: request was passed to
>>> EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>> corresponding to THIS HibernatePersistableEList was loaded all
>>> objects contained in PersistentBag are added to resource - it's OK.
>>>
>>> PROBLEM:
>>>
>>> Actually in my example THREE PersistentBag were loaded - cause three
>>> object with such lazy collections are already loaded - try to
>>> investigate org.hibernate.engine.endLoadingCollections() method - it
>>> has following code:
>>>
>>> final int count = (resultSetCollections == null) ? 0 :
>>> resultSetCollections.size();
>>>
>>> if ( log.isDebugEnabled() ) {
>>> log.debug( count + " collections were found in result set
>>> for role: " + persister.getRole() );
>>> }
>>>
>>> //now finish them
>>> for ( int i = 0; i < count; i++ ) {
>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>> resultSetCollections.get(i);
>>> endLoadingCollection(lce, persister, em);
>>> }
>>>
>>> if ( log.isDebugEnabled() ) {
>>> log.debug( count + " collections initialized for role: "
>>> + persister.getRole() );
>>> }
>>>
>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>> happened because my association has fetch="subselect".
>>>
>>> So THREE PersistentBags were were marked as initialized but ONLY
>>> object from ONE OF THEM were added to contents of resource.
>>>
>>> Why other were not added?
>>>
>>> Answer is simple:
>>> Method doLoad() was not called for two other
>>> HibernatePersistableEList. Adding objects to resource.contents() is
>>> in this method. Why was notthis method called to two other list?
>>> Cause it is called only if isLoaded() returns false.
>>>
>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>
>>> public boolean isLoaded() {
>>> if (delegate instanceof AbstractPersistentCollection) {
>>> if (((AbstractPersistentCollection)
>>> delegate).wasInitialized()) {
>>> setIsLoaded(true);
>>> // log.debug("Persistentlist already initialized,
>>> probably eagerly loaded: " + getLogString());
>>> }
>>> }
>>> return super.isLoaded();
>>> }
>>>
>>> So let me describe full chain of events:
>>>
>>> There are THREE objects with lazy not loaded collections with
>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>> for collection it force hibernate to load this collection via
>>>
>>> Object[] objs = delegate.toArray(); // this forces the load
>>>
>>> and adds objects to resource.
>>>
>>> BUT during forcing of loading one delegate two other delegates were
>>> loaded too - they were marked as initialized. So two other
>>> HibernatePersistableELists will return isLoaded() = true because:
>>>
>>> public boolean isLoaded() {
>>> if (delegate instanceof AbstractPersistentCollection) {
>>> if (((AbstractPersistentCollection)
>>> delegate).wasInitialized()) {
>>> setIsLoaded(true);
>>> // log.debug("Persistentlist already initialized,
>>> probably eagerly loaded: " + getLogString());
>>> }
>>> }
>>> return super.isLoaded();
>>> }
>>>
>>> So Teneo looses the moment when delegate is really initialized.
>>>
>>> This happens when fetch="subselect". Details of how fetch="subselect"
>>> works are in hibernate docs.
>>>
>>> My proposals:
>>> You can override setIsLoaded() in HibernatePersistableELists and
>>> check that objects are added - then isLoaded needs to be implemented
>>> like:
>>>
>>> public boolean isLoaded() {
>>> if (isLoaded){
>>> return true;
>>> }
>>> if (delegate instanceof AbstractPersistentCollection) {
>>> if (((AbstractPersistentCollection)
>>> delegate).wasInitialized()) {
>>> setIsLoaded(true);
>>> // log.debug("Persistentlist already initialized,
>>> probably eagerly loaded: " + getLogString());
>>> }
>>> }
>>> return super.isLoaded();
>>> }
>>>
>>> Feel free to ask me for more details if my answer is not enough.
>>>
>>> Ilya
>>>
>>> Martin Taal wrote:
>>>> I do not fully understand what happens here. Can you describe the
>>>> case/example in which this occurs (automatically loading other such
>>>> collections)? The hibernate behavior as you describe it is
>>>> unfamiliar to me.
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> When I use HibernateResource with loading strategy addToContents
>>>>> then all is OK until I have created association with
>>>>> fetch="subselect".
>>>>> Sometimes objects that are inside these lazy collections are loaded
>>>>> they are not added to resource.
>>>>>
>>>>> As far as I understand it happens when I ask some objects from ONE
>>>>> such collection BUT if there are any other such collections that
>>>>> are not loaded Hibernate can load all such collections. And fact of
>>>>> loading of other collections are not caught by Teneo.
>>>>>
>>>>> Is this a bug?
>>>>>
>>>>> Thanks
>>>>>
>>>>> Ilya
>>>>
>>>>
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65705 is a reply to message #65683] |
Wed, 27 December 2006 14:10 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Yes for eagerly loaded lists I understand the issue. What I don't understand is why the lazy loaded
collections are loaded (automatically). You say:
>>>> Actually in my example THREE PersistentBag were loaded - cause three
>>>> object with such lazy collections are already loaded
What do you mean?
gr. Martin
Ilya Klyuchnikov wrote:
> In my example lazy="true".
>
> BTW, if there are collections with lazy="false" then during resource
> loading objects in such collections are not added to resource.
>
> Martin Taal wrote:
>> Hi Ilya,
>> Yes the solution is in the isLoaded method. If the underlying
>> hibernate collection is already loaded/initialized while
>> isLoaded=false then the children need to be added to the resource
>> (calling doLoad with some extra handling should work).
>>
>> Are the automatically loaded collections eager or lazy?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>
>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>> instead of org.hibernate.engine.endLoadingCollections()
>>>
>>> Ilya
>>>
>>> Ilya Klyuchnikov wrote:
>>>> Hi Martin
>>>>
>>>> I suppose that these details help you to understand problem:
>>>>
>>>> This is stack trace:
>>>>
>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>> AbstractPersistentCollection))
>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>> 366
>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>>>> 319 PersistentBag(AbstractPersistentCollection).endRead()
>>>> line: 315
>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>> CollectionPersister, EntityMode) line: 183
>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>> List, EntityMode) line: 268
>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>> Object, SessionImplementor) line: 249
>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>> SessionImplementor, CollectionPersister) line: 866
>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>> Object, SessionImplementor, boolean) line: 853
>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>> QueryParameters, boolean) line: 717
>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>> QueryParameters, boolean) line: 224
>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>> SessionImplementor) line: 58
>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>> SessionImplementor) line: 565
>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>> line: 60
>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>> line: 1716
>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>> line: 86 PersistentBag.toArray() line: 257
>>>> HibernatePersistableEList.doLoad() line: 106
>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>> line: 339
>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>> line: 380 As you see activity begins with:
>>>> HibernatePersistableEList.doLoad() line: 106
>>>>
>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>
>>>> PROBLEM:
>>>>
>>>> Actually in my example THREE PersistentBag were loaded - cause three
>>>> object with such lazy collections are already loaded - try to
>>>> investigate org.hibernate.engine.endLoadingCollections() method - it
>>>> has following code:
>>>>
>>>> final int count = (resultSetCollections == null) ? 0 :
>>>> resultSetCollections.size();
>>>>
>>>> if ( log.isDebugEnabled() ) {
>>>> log.debug( count + " collections were found in result
>>>> set for role: " + persister.getRole() );
>>>> }
>>>>
>>>> //now finish them
>>>> for ( int i = 0; i < count; i++ ) {
>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>> resultSetCollections.get(i);
>>>> endLoadingCollection(lce, persister, em);
>>>> }
>>>>
>>>> if ( log.isDebugEnabled() ) {
>>>> log.debug( count + " collections initialized for role: "
>>>> + persister.getRole() );
>>>> }
>>>>
>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>> happened because my association has fetch="subselect".
>>>>
>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>> object from ONE OF THEM were added to contents of resource.
>>>>
>>>> Why other were not added?
>>>>
>>>> Answer is simple:
>>>> Method doLoad() was not called for two other
>>>> HibernatePersistableEList. Adding objects to resource.contents() is
>>>> in this method. Why was notthis method called to two other list?
>>>> Cause it is called only if isLoaded() returns false.
>>>>
>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>
>>>> public boolean isLoaded() {
>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>> if (((AbstractPersistentCollection)
>>>> delegate).wasInitialized()) {
>>>> setIsLoaded(true);
>>>> // log.debug("Persistentlist already initialized,
>>>> probably eagerly loaded: " + getLogString());
>>>> }
>>>> }
>>>> return super.isLoaded();
>>>> }
>>>>
>>>> So let me describe full chain of events:
>>>>
>>>> There are THREE objects with lazy not loaded collections with
>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>> for collection it force hibernate to load this collection via
>>>>
>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>
>>>> and adds objects to resource.
>>>>
>>>> BUT during forcing of loading one delegate two other delegates were
>>>> loaded too - they were marked as initialized. So two other
>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>
>>>> public boolean isLoaded() {
>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>> if (((AbstractPersistentCollection)
>>>> delegate).wasInitialized()) {
>>>> setIsLoaded(true);
>>>> // log.debug("Persistentlist already initialized,
>>>> probably eagerly loaded: " + getLogString());
>>>> }
>>>> }
>>>> return super.isLoaded();
>>>> }
>>>>
>>>> So Teneo looses the moment when delegate is really initialized.
>>>>
>>>> This happens when fetch="subselect". Details of how
>>>> fetch="subselect" works are in hibernate docs.
>>>>
>>>> My proposals:
>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>> check that objects are added - then isLoaded needs to be implemented
>>>> like:
>>>>
>>>> public boolean isLoaded() {
>>>> if (isLoaded){
>>>> return true;
>>>> }
>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>> if (((AbstractPersistentCollection)
>>>> delegate).wasInitialized()) {
>>>> setIsLoaded(true);
>>>> // log.debug("Persistentlist already initialized,
>>>> probably eagerly loaded: " + getLogString());
>>>> }
>>>> }
>>>> return super.isLoaded();
>>>> }
>>>>
>>>> Feel free to ask me for more details if my answer is not enough.
>>>>
>>>> Ilya
>>>>
>>>> Martin Taal wrote:
>>>>> I do not fully understand what happens here. Can you describe the
>>>>> case/example in which this occurs (automatically loading other such
>>>>> collections)? The hibernate behavior as you describe it is
>>>>> unfamiliar to me.
>>>>>
>>>>> gr. Martin
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>> then all is OK until I have created association with
>>>>>> fetch="subselect".
>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>> loaded they are not added to resource.
>>>>>>
>>>>>> As far as I understand it happens when I ask some objects from ONE
>>>>>> such collection BUT if there are any other such collections that
>>>>>> are not loaded Hibernate can load all such collections. And fact
>>>>>> of loading of other collections are not caught by Teneo.
>>>>>>
>>>>>> Is this a bug?
>>>>>>
>>>>>> Thanks
>>>>>>
>>>>>> Ilya
>>>>>
>>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65752 is a reply to message #65705] |
Wed, 27 December 2006 14:25 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
The reason that fetch="subselect":
With fetch="subselect" Hibernate loads ALL such collections on demand.
In my example when I ask DeploymentEnvironment.getDomains() Hibernate
generates such query:
Hibernate: select domain0_.`environment_id` as environm6_1_,
domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_, domain0_.e_version
as e3_21_0_, domain0_.`name` as name4_21_0_, domain0_.`modified` as
modified5_21_0_, domain0_.`environment_id` as environm6_21_0_ from
`domain` domain0_ where domain0_.`environment_id` in (select
deployment1_.`id` from environment_deploys deploysto0_ left outer join
`environment` deployment1_ on deploysto0_.`from_id`=deployment1_.`id`
where deploysto0_.`to_id`=?)
Put attentions to where domain0_.`environment_id` in ...
So this is a feature of Hibernate:
If there are some not loaded collection corresponding to the same
association (DeploymentEnvironment.domains in my example) having
fetch="subselect" and client ask ONE of these collections to be loaded
then Hibernate loads ALL collections. You can see this logic in
AbstractCollectionPersister class.
See
http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
for details.
Ilya
Martin Taal wrote:
> Yes for eagerly loaded lists I understand the issue. What I don't
> understand is why the lazy loaded collections are loaded
> (automatically). You say:
> >>>> Actually in my example THREE PersistentBag were loaded - cause three
> >>>> object with such lazy collections are already loaded
>
> What do you mean?
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> In my example lazy="true".
>>
>> BTW, if there are collections with lazy="false" then during resource
>> loading objects in such collections are not added to resource.
>>
>> Martin Taal wrote:
>>> Hi Ilya,
>>> Yes the solution is in the isLoaded method. If the underlying
>>> hibernate collection is already loaded/initialized while
>>> isLoaded=false then the children need to be added to the resource
>>> (calling doLoad with some extra handling should work).
>>>
>>> Are the automatically loaded collections eager or lazy?
>>>
>>> gr. Martin
>>>
>>> Ilya Klyuchnikov wrote:
>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>
>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>
>>>> Ilya
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> Hi Martin
>>>>>
>>>>> I suppose that these details help you to understand problem:
>>>>>
>>>>> This is stack trace:
>>>>>
>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>> AbstractPersistentCollection))
>>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>>> 366
>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>>>>> 319 PersistentBag(AbstractPersistentCollection).endRead()
>>>>> line: 315
>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>> CollectionPersister, EntityMode) line: 183
>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>> List, EntityMode) line: 268
>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>> Object, SessionImplementor) line: 249
>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>> Object, SessionImplementor, boolean) line: 853
>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>> QueryParameters, boolean) line: 717
>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>> QueryParameters, boolean) line: 224
>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>> SessionImplementor) line: 58
>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>> SessionImplementor) line: 565
>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>> line: 60
>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>> line: 1716
>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>>> line: 86 PersistentBag.toArray() line: 257
>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>> line: 339
>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>> line: 380 As you see activity begins with:
>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>
>>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>>
>>>>> PROBLEM:
>>>>>
>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>> three object with such lazy collections are already loaded - try to
>>>>> investigate org.hibernate.engine.endLoadingCollections() method -
>>>>> it has following code:
>>>>>
>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>> resultSetCollections.size();
>>>>>
>>>>> if ( log.isDebugEnabled() ) {
>>>>> log.debug( count + " collections were found in result
>>>>> set for role: " + persister.getRole() );
>>>>> }
>>>>>
>>>>> //now finish them
>>>>> for ( int i = 0; i < count; i++ ) {
>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>> resultSetCollections.get(i);
>>>>> endLoadingCollection(lce, persister, em);
>>>>> }
>>>>>
>>>>> if ( log.isDebugEnabled() ) {
>>>>> log.debug( count + " collections initialized for role:
>>>>> " + persister.getRole() );
>>>>> }
>>>>>
>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>> happened because my association has fetch="subselect".
>>>>>
>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>
>>>>> Why other were not added?
>>>>>
>>>>> Answer is simple:
>>>>> Method doLoad() was not called for two other
>>>>> HibernatePersistableEList. Adding objects to resource.contents() is
>>>>> in this method. Why was notthis method called to two other list?
>>>>> Cause it is called only if isLoaded() returns false.
>>>>>
>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>
>>>>> public boolean isLoaded() {
>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>> if (((AbstractPersistentCollection)
>>>>> delegate).wasInitialized()) {
>>>>> setIsLoaded(true);
>>>>> // log.debug("Persistentlist already initialized,
>>>>> probably eagerly loaded: " + getLogString());
>>>>> }
>>>>> }
>>>>> return super.isLoaded();
>>>>> }
>>>>>
>>>>> So let me describe full chain of events:
>>>>>
>>>>> There are THREE objects with lazy not loaded collections with
>>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>>> for collection it force hibernate to load this collection via
>>>>>
>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>
>>>>> and adds objects to resource.
>>>>>
>>>>> BUT during forcing of loading one delegate two other delegates were
>>>>> loaded too - they were marked as initialized. So two other
>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>
>>>>> public boolean isLoaded() {
>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>> if (((AbstractPersistentCollection)
>>>>> delegate).wasInitialized()) {
>>>>> setIsLoaded(true);
>>>>> // log.debug("Persistentlist already initialized,
>>>>> probably eagerly loaded: " + getLogString());
>>>>> }
>>>>> }
>>>>> return super.isLoaded();
>>>>> }
>>>>>
>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>
>>>>> This happens when fetch="subselect". Details of how
>>>>> fetch="subselect" works are in hibernate docs.
>>>>>
>>>>> My proposals:
>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>> check that objects are added - then isLoaded needs to be
>>>>> implemented like:
>>>>>
>>>>> public boolean isLoaded() {
>>>>> if (isLoaded){
>>>>> return true;
>>>>> }
>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>> if (((AbstractPersistentCollection)
>>>>> delegate).wasInitialized()) {
>>>>> setIsLoaded(true);
>>>>> // log.debug("Persistentlist already initialized,
>>>>> probably eagerly loaded: " + getLogString());
>>>>> }
>>>>> }
>>>>> return super.isLoaded();
>>>>> }
>>>>>
>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>
>>>>> Ilya
>>>>>
>>>>> Martin Taal wrote:
>>>>>> I do not fully understand what happens here. Can you describe the
>>>>>> case/example in which this occurs (automatically loading other
>>>>>> such collections)? The hibernate behavior as you describe it is
>>>>>> unfamiliar to me.
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>> Ilya Klyuchnikov wrote:
>>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>>> then all is OK until I have created association with
>>>>>>> fetch="subselect".
>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>> loaded they are not added to resource.
>>>>>>>
>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>> that are not loaded Hibernate can load all such collections. And
>>>>>>> fact of loading of other collections are not caught by Teneo.
>>>>>>>
>>>>>>> Is this a bug?
>>>>>>>
>>>>>>> Thanks
>>>>>>>
>>>>>>> Ilya
>>>>>>
>>>>>>
>>>
>>>
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65775 is a reply to message #65752] |
Wed, 27 December 2006 14:28 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Quotes from hibernate documentaion
( http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching):
Subselect fetching - a second SELECT is used to retrieve the associated
collections for ALL entities retrieved in a previous query or fetch.
Unless you explicitly disable lazy fetching by specifying lazy="false",
this second select will only be executed when you actually access the
association.
Ilya
Ilya Klyuchnikov wrote:
> The reason that fetch="subselect":
>
> With fetch="subselect" Hibernate loads ALL such collections on demand.
>
> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
> generates such query:
>
> Hibernate: select domain0_.`environment_id` as environm6_1_,
> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_, domain0_.e_version
> as e3_21_0_, domain0_.`name` as name4_21_0_, domain0_.`modified` as
> modified5_21_0_, domain0_.`environment_id` as environm6_21_0_ from
> `domain` domain0_ where domain0_.`environment_id` in (select
> deployment1_.`id` from environment_deploys deploysto0_ left outer join
> `environment` deployment1_ on deploysto0_.`from_id`=deployment1_.`id`
> where deploysto0_.`to_id`=?)
>
> Put attentions to where domain0_.`environment_id` in ...
>
> So this is a feature of Hibernate:
> If there are some not loaded collection corresponding to the same
> association (DeploymentEnvironment.domains in my example) having
> fetch="subselect" and client ask ONE of these collections to be loaded
> then Hibernate loads ALL collections. You can see this logic in
> AbstractCollectionPersister class.
>
> See
> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
> for details.
>
> Ilya
>
> Martin Taal wrote:
>> Yes for eagerly loaded lists I understand the issue. What I don't
>> understand is why the lazy loaded collections are loaded
>> (automatically). You say:
>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>> three
>> >>>> object with such lazy collections are already loaded
>>
>> What do you mean?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> In my example lazy="true".
>>>
>>> BTW, if there are collections with lazy="false" then during resource
>>> loading objects in such collections are not added to resource.
>>>
>>> Martin Taal wrote:
>>>> Hi Ilya,
>>>> Yes the solution is in the isLoaded method. If the underlying
>>>> hibernate collection is already loaded/initialized while
>>>> isLoaded=false then the children need to be added to the resource
>>>> (calling doLoad with some extra handling should work).
>>>>
>>>> Are the automatically loaded collections eager or lazy?
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>
>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>
>>>>> Ilya
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> Hi Martin
>>>>>>
>>>>>> I suppose that these details help you to understand problem:
>>>>>>
>>>>>> This is stack trace:
>>>>>>
>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>> AbstractPersistentCollection))
>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>>>> 366
>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>> line: 319
>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>> 315
>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> List, EntityMode) line: 268
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> Object, SessionImplementor) line: 249
>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 717
>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 224
>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>> SessionImplementor) line: 58
>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>> SessionImplementor) line: 565
>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>> line: 60
>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>> line: 1716
>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>>>> line: 86 PersistentBag.toArray() line: 257
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>> line: 339
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>> line: 380 As you see activity begins with:
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>
>>>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>>>
>>>>>> PROBLEM:
>>>>>>
>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>> three object with such lazy collections are already loaded - try
>>>>>> to investigate org.hibernate.engine.endLoadingCollections() method
>>>>>> - it has following code:
>>>>>>
>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>> resultSetCollections.size();
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections were found in result
>>>>>> set for role: " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> //now finish them
>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>>> resultSetCollections.get(i);
>>>>>> endLoadingCollection(lce, persister, em);
>>>>>> }
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections initialized for role:
>>>>>> " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>>> happened because my association has fetch="subselect".
>>>>>>
>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>
>>>>>> Why other were not added?
>>>>>>
>>>>>> Answer is simple:
>>>>>> Method doLoad() was not called for two other
>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>> is in this method. Why was notthis method called to two other
>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>
>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So let me describe full chain of events:
>>>>>>
>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>>>> for collection it force hibernate to load this collection via
>>>>>>
>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>
>>>>>> and adds objects to resource.
>>>>>>
>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>
>>>>>> This happens when fetch="subselect". Details of how
>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>
>>>>>> My proposals:
>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>> check that objects are added - then isLoaded needs to be
>>>>>> implemented like:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (isLoaded){
>>>>>> return true;
>>>>>> }
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>
>>>>>> Ilya
>>>>>>
>>>>>> Martin Taal wrote:
>>>>>>> I do not fully understand what happens here. Can you describe the
>>>>>>> case/example in which this occurs (automatically loading other
>>>>>>> such collections)? The hibernate behavior as you describe it is
>>>>>>> unfamiliar to me.
>>>>>>>
>>>>>>> gr. Martin
>>>>>>>
>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>>>> then all is OK until I have created association with
>>>>>>>> fetch="subselect".
>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>> loaded they are not added to resource.
>>>>>>>>
>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>>> that are not loaded Hibernate can load all such collections. And
>>>>>>>> fact of loading of other collections are not caught by Teneo.
>>>>>>>>
>>>>>>>> Is this a bug?
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>>> Ilya
>>>>>>>
>>>>>>>
>>>>
>>>>
>>
>>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65798 is a reply to message #65752] |
Wed, 27 December 2006 14:28 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Okay, clear, I will commit a fix for this this evening. Are you able to test the cvs version or make
the change locally?
gr. Martin
Ilya Klyuchnikov wrote:
> The reason that fetch="subselect":
>
> With fetch="subselect" Hibernate loads ALL such collections on demand.
>
> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
> generates such query:
>
> Hibernate: select domain0_.`environment_id` as environm6_1_,
> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_, domain0_.e_version
> as e3_21_0_, domain0_.`name` as name4_21_0_, domain0_.`modified` as
> modified5_21_0_, domain0_.`environment_id` as environm6_21_0_ from
> `domain` domain0_ where domain0_.`environment_id` in (select
> deployment1_.`id` from environment_deploys deploysto0_ left outer join
> `environment` deployment1_ on deploysto0_.`from_id`=deployment1_.`id`
> where deploysto0_.`to_id`=?)
>
> Put attentions to where domain0_.`environment_id` in ...
>
> So this is a feature of Hibernate:
> If there are some not loaded collection corresponding to the same
> association (DeploymentEnvironment.domains in my example) having
> fetch="subselect" and client ask ONE of these collections to be loaded
> then Hibernate loads ALL collections. You can see this logic in
> AbstractCollectionPersister class.
>
> See
> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
> for details.
>
> Ilya
>
> Martin Taal wrote:
>> Yes for eagerly loaded lists I understand the issue. What I don't
>> understand is why the lazy loaded collections are loaded
>> (automatically). You say:
>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>> three
>> >>>> object with such lazy collections are already loaded
>>
>> What do you mean?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> In my example lazy="true".
>>>
>>> BTW, if there are collections with lazy="false" then during resource
>>> loading objects in such collections are not added to resource.
>>>
>>> Martin Taal wrote:
>>>> Hi Ilya,
>>>> Yes the solution is in the isLoaded method. If the underlying
>>>> hibernate collection is already loaded/initialized while
>>>> isLoaded=false then the children need to be added to the resource
>>>> (calling doLoad with some extra handling should work).
>>>>
>>>> Are the automatically loaded collections eager or lazy?
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>
>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>
>>>>> Ilya
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> Hi Martin
>>>>>>
>>>>>> I suppose that these details help you to understand problem:
>>>>>>
>>>>>> This is stack trace:
>>>>>>
>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>> AbstractPersistentCollection))
>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>>>> 366
>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>> line: 319
>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>> 315
>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> List, EntityMode) line: 268
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> Object, SessionImplementor) line: 249
>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 717
>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 224
>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>> SessionImplementor) line: 58
>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>> SessionImplementor) line: 565
>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>> line: 60
>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>> line: 1716
>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>>>> line: 86 PersistentBag.toArray() line: 257
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>> line: 339
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>> line: 380 As you see activity begins with:
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>
>>>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>>>
>>>>>> PROBLEM:
>>>>>>
>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>> three object with such lazy collections are already loaded - try
>>>>>> to investigate org.hibernate.engine.endLoadingCollections() method
>>>>>> - it has following code:
>>>>>>
>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>> resultSetCollections.size();
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections were found in result
>>>>>> set for role: " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> //now finish them
>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>>> resultSetCollections.get(i);
>>>>>> endLoadingCollection(lce, persister, em);
>>>>>> }
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections initialized for role:
>>>>>> " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>>> happened because my association has fetch="subselect".
>>>>>>
>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>
>>>>>> Why other were not added?
>>>>>>
>>>>>> Answer is simple:
>>>>>> Method doLoad() was not called for two other
>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>> is in this method. Why was notthis method called to two other
>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>
>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So let me describe full chain of events:
>>>>>>
>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>>>> for collection it force hibernate to load this collection via
>>>>>>
>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>
>>>>>> and adds objects to resource.
>>>>>>
>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>
>>>>>> This happens when fetch="subselect". Details of how
>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>
>>>>>> My proposals:
>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>> check that objects are added - then isLoaded needs to be
>>>>>> implemented like:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (isLoaded){
>>>>>> return true;
>>>>>> }
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>
>>>>>> Ilya
>>>>>>
>>>>>> Martin Taal wrote:
>>>>>>> I do not fully understand what happens here. Can you describe the
>>>>>>> case/example in which this occurs (automatically loading other
>>>>>>> such collections)? The hibernate behavior as you describe it is
>>>>>>> unfamiliar to me.
>>>>>>>
>>>>>>> gr. Martin
>>>>>>>
>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>>>> then all is OK until I have created association with
>>>>>>>> fetch="subselect".
>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>> loaded they are not added to resource.
>>>>>>>>
>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>>> that are not loaded Hibernate can load all such collections. And
>>>>>>>> fact of loading of other collections are not caught by Teneo.
>>>>>>>>
>>>>>>>> Is this a bug?
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>>> Ilya
>>>>>>>
>>>>>>>
>>>>
>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65822 is a reply to message #65798] |
Wed, 27 December 2006 15:24 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) ![Go to next message Go to next message](theme/Solstice/images/down.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Sorry Martin,
It is time consuming for me to build and test Teneo cvs version.
I think that I will be able to test your changes on Friday evening only.
Ilya
Martin Taal wrote:
> Okay, clear, I will commit a fix for this this evening. Are you able to
> test the cvs version or make the change locally?
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> The reason that fetch="subselect":
>>
>> With fetch="subselect" Hibernate loads ALL such collections on demand.
>>
>> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
>> generates such query:
>>
>> Hibernate: select domain0_.`environment_id` as environm6_1_,
>> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_,
>> domain0_.e_version as e3_21_0_, domain0_.`name` as name4_21_0_,
>> domain0_.`modified` as modified5_21_0_, domain0_.`environment_id` as
>> environm6_21_0_ from `domain` domain0_ where domain0_.`environment_id`
>> in (select deployment1_.`id` from environment_deploys deploysto0_ left
>> outer join `environment` deployment1_ on
>> deploysto0_.`from_id`=deployment1_.`id` where deploysto0_.`to_id`=?)
>>
>> Put attentions to where domain0_.`environment_id` in ...
>>
>> So this is a feature of Hibernate:
>> If there are some not loaded collection corresponding to the same
>> association (DeploymentEnvironment.domains in my example) having
>> fetch="subselect" and client ask ONE of these collections to be loaded
>> then Hibernate loads ALL collections. You can see this logic in
>> AbstractCollectionPersister class.
>>
>> See
>> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
>> for details.
>>
>> Ilya
>>
>> Martin Taal wrote:
>>> Yes for eagerly loaded lists I understand the issue. What I don't
>>> understand is why the lazy loaded collections are loaded
>>> (automatically). You say:
>>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>>> three
>>> >>>> object with such lazy collections are already loaded
>>>
>>> What do you mean?
>>>
>>> gr. Martin
>>>
>>> Ilya Klyuchnikov wrote:
>>>> In my example lazy="true".
>>>>
>>>> BTW, if there are collections with lazy="false" then during resource
>>>> loading objects in such collections are not added to resource.
>>>>
>>>> Martin Taal wrote:
>>>>> Hi Ilya,
>>>>> Yes the solution is in the isLoaded method. If the underlying
>>>>> hibernate collection is already loaded/initialized while
>>>>> isLoaded=false then the children need to be added to the resource
>>>>> (calling doLoad with some extra handling should work).
>>>>>
>>>>> Are the automatically loaded collections eager or lazy?
>>>>>
>>>>> gr. Martin
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>>
>>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>>
>>>>>> Ilya
>>>>>>
>>>>>> Ilya Klyuchnikov wrote:
>>>>>>> Hi Martin
>>>>>>>
>>>>>>> I suppose that these details help you to understand problem:
>>>>>>>
>>>>>>> This is stack trace:
>>>>>>>
>>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>>> AbstractPersistentCollection))
>>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized()
>>>>>>> line: 366
>>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>>> line: 319
>>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>>> 315
>>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>> List, EntityMode) line: 268
>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>> Object, SessionImplementor) line: 249
>>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>>> QueryParameters, boolean) line: 717
>>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>>> QueryParameters, boolean) line: 224
>>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>>> SessionImplementor) line: 58
>>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>>> SessionImplementor) line: 565
>>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>>> line: 60
>>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>>> line: 1716
>>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>>> line: 344
>>>>>>> PersistentBag(AbstractPersistentCollection).read() line: 86
>>>>>>> PersistentBag.toArray() line: 257
>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>> HibernatePersistableEList(PersistableEList).load() line:
>>>>>>> 187
>>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>>> line: 339
>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>>> line: 380 As you see activity begins with:
>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>>
>>>>>>> and PersistentBag is marked as initialized BUT: request was
>>>>>>> passed to EXACTLY ONE HibernatePersistableEList - so after
>>>>>>> PersistentBag corresponding to THIS HibernatePersistableEList was
>>>>>>> loaded all objects contained in PersistentBag are added to
>>>>>>> resource - it's OK.
>>>>>>>
>>>>>>> PROBLEM:
>>>>>>>
>>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>>> three object with such lazy collections are already loaded - try
>>>>>>> to investigate org.hibernate.engine.endLoadingCollections()
>>>>>>> method - it has following code:
>>>>>>>
>>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>>> resultSetCollections.size();
>>>>>>>
>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>> log.debug( count + " collections were found in result
>>>>>>> set for role: " + persister.getRole() );
>>>>>>> }
>>>>>>>
>>>>>>> //now finish them
>>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>>>> resultSetCollections.get(i);
>>>>>>> endLoadingCollection(lce, persister, em);
>>>>>>> }
>>>>>>>
>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>> log.debug( count + " collections initialized for
>>>>>>> role: " + persister.getRole() );
>>>>>>> }
>>>>>>>
>>>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>>>> happened because my association has fetch="subselect".
>>>>>>>
>>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>>
>>>>>>> Why other were not added?
>>>>>>>
>>>>>>> Answer is simple:
>>>>>>> Method doLoad() was not called for two other
>>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>>> is in this method. Why was notthis method called to two other
>>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>>
>>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>>
>>>>>>> public boolean isLoaded() {
>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>> if (((AbstractPersistentCollection)
>>>>>>> delegate).wasInitialized()) {
>>>>>>> setIsLoaded(true);
>>>>>>> // log.debug("Persistentlist already initialized,
>>>>>>> probably eagerly loaded: " + getLogString());
>>>>>>> }
>>>>>>> }
>>>>>>> return super.isLoaded();
>>>>>>> }
>>>>>>>
>>>>>>> So let me describe full chain of events:
>>>>>>>
>>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>>> fetch="subselect". When one of HibernatePersistableELists is
>>>>>>> asked for collection it force hibernate to load this collection via
>>>>>>>
>>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>>
>>>>>>> and adds objects to resource.
>>>>>>>
>>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>>
>>>>>>> public boolean isLoaded() {
>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>> if (((AbstractPersistentCollection)
>>>>>>> delegate).wasInitialized()) {
>>>>>>> setIsLoaded(true);
>>>>>>> // log.debug("Persistentlist already initialized,
>>>>>>> probably eagerly loaded: " + getLogString());
>>>>>>> }
>>>>>>> }
>>>>>>> return super.isLoaded();
>>>>>>> }
>>>>>>>
>>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>>
>>>>>>> This happens when fetch="subselect". Details of how
>>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>>
>>>>>>> My proposals:
>>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>>> check that objects are added - then isLoaded needs to be
>>>>>>> implemented like:
>>>>>>>
>>>>>>> public boolean isLoaded() {
>>>>>>> if (isLoaded){
>>>>>>> return true;
>>>>>>> }
>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>> if (((AbstractPersistentCollection)
>>>>>>> delegate).wasInitialized()) {
>>>>>>> setIsLoaded(true);
>>>>>>> // log.debug("Persistentlist already initialized,
>>>>>>> probably eagerly loaded: " + getLogString());
>>>>>>> }
>>>>>>> }
>>>>>>> return super.isLoaded();
>>>>>>> }
>>>>>>>
>>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>>
>>>>>>> Ilya
>>>>>>>
>>>>>>> Martin Taal wrote:
>>>>>>>> I do not fully understand what happens here. Can you describe
>>>>>>>> the case/example in which this occurs (automatically loading
>>>>>>>> other such collections)? The hibernate behavior as you describe
>>>>>>>> it is unfamiliar to me.
>>>>>>>>
>>>>>>>> gr. Martin
>>>>>>>>
>>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>>> When I use HibernateResource with loading strategy
>>>>>>>>> addToContents then all is OK until I have created association
>>>>>>>>> with fetch="subselect".
>>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>>> loaded they are not added to resource.
>>>>>>>>>
>>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>>>> that are not loaded Hibernate can load all such collections.
>>>>>>>>> And fact of loading of other collections are not caught by Teneo.
>>>>>>>>>
>>>>>>>>> Is this a bug?
>>>>>>>>>
>>>>>>>>> Thanks
>>>>>>>>>
>>>>>>>>> Ilya
>>>>>>>>
>>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #65977 is a reply to message #65822] |
Fri, 29 December 2006 08:19 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Hi Ilya,
You can try the latest build here, that's easier then using the cvs version:
http://emft.eclipse.org/emft/downloads/index.php?project=ten eo&showAll=0&showMax=10&sortBy=date
gr. Martin
Ilya Klyuchnikov wrote:
> Sorry Martin,
>
> It is time consuming for me to build and test Teneo cvs version.
>
> I think that I will be able to test your changes on Friday evening only.
>
> Ilya
>
> Martin Taal wrote:
>> Okay, clear, I will commit a fix for this this evening. Are you able
>> to test the cvs version or make the change locally?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> The reason that fetch="subselect":
>>>
>>> With fetch="subselect" Hibernate loads ALL such collections on demand.
>>>
>>> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
>>> generates such query:
>>>
>>> Hibernate: select domain0_.`environment_id` as environm6_1_,
>>> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_,
>>> domain0_.e_version as e3_21_0_, domain0_.`name` as name4_21_0_,
>>> domain0_.`modified` as modified5_21_0_, domain0_.`environment_id` as
>>> environm6_21_0_ from `domain` domain0_ where
>>> domain0_.`environment_id` in (select deployment1_.`id` from
>>> environment_deploys deploysto0_ left outer join `environment`
>>> deployment1_ on deploysto0_.`from_id`=deployment1_.`id` where
>>> deploysto0_.`to_id`=?)
>>>
>>> Put attentions to where domain0_.`environment_id` in ...
>>>
>>> So this is a feature of Hibernate:
>>> If there are some not loaded collection corresponding to the same
>>> association (DeploymentEnvironment.domains in my example) having
>>> fetch="subselect" and client ask ONE of these collections to be
>>> loaded then Hibernate loads ALL collections. You can see this logic
>>> in AbstractCollectionPersister class.
>>>
>>> See
>>> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
>>> for details.
>>>
>>> Ilya
>>>
>>> Martin Taal wrote:
>>>> Yes for eagerly loaded lists I understand the issue. What I don't
>>>> understand is why the lazy loaded collections are loaded
>>>> (automatically). You say:
>>>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>>>> three
>>>> >>>> object with such lazy collections are already loaded
>>>>
>>>> What do you mean?
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> In my example lazy="true".
>>>>>
>>>>> BTW, if there are collections with lazy="false" then during
>>>>> resource loading objects in such collections are not added to
>>>>> resource.
>>>>>
>>>>> Martin Taal wrote:
>>>>>> Hi Ilya,
>>>>>> Yes the solution is in the isLoaded method. If the underlying
>>>>>> hibernate collection is already loaded/initialized while
>>>>>> isLoaded=false then the children need to be added to the resource
>>>>>> (calling doLoad with some extra handling should work).
>>>>>>
>>>>>> Are the automatically loaded collections eager or lazy?
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>> Ilya Klyuchnikov wrote:
>>>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>>>
>>>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>>>
>>>>>>> Ilya
>>>>>>>
>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>> Hi Martin
>>>>>>>>
>>>>>>>> I suppose that these details help you to understand problem:
>>>>>>>>
>>>>>>>> This is stack trace:
>>>>>>>>
>>>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>>>> AbstractPersistentCollection))
>>>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized()
>>>>>>>> line: 366
>>>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>>>> line: 319
>>>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>>>> 315
>>>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>>> List, EntityMode) line: 268
>>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>>> Object, SessionImplementor) line: 249
>>>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>>>> QueryParameters, boolean) line: 717
>>>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>>>> QueryParameters, boolean) line: 224
>>>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>>>> SessionImplementor) line: 58
>>>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>>>> SessionImplementor) line: 565
>>>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>>>> line: 60
>>>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>>>> line: 1716
>>>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>>>> line: 344
>>>>>>>> PersistentBag(AbstractPersistentCollection).read() line:
>>>>>>>> 86 PersistentBag.toArray() line: 257
>>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>>> HibernatePersistableEList(PersistableEList).load() line:
>>>>>>>> 187
>>>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>>>> 395 HibernatePersistableEList(DelegatingEList).size()
>>>>>>>> line: 214 DelegatingEList$EIterator.hasNext() line:
>>>>>>>> 1000
>>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>>>> line: 339
>>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>>>> line: 380 As you see activity begins with:
>>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>>>
>>>>>>>> and PersistentBag is marked as initialized BUT: request was
>>>>>>>> passed to EXACTLY ONE HibernatePersistableEList - so after
>>>>>>>> PersistentBag corresponding to THIS HibernatePersistableEList
>>>>>>>> was loaded all objects contained in PersistentBag are added to
>>>>>>>> resource - it's OK.
>>>>>>>>
>>>>>>>> PROBLEM:
>>>>>>>>
>>>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>>>> three object with such lazy collections are already loaded - try
>>>>>>>> to investigate org.hibernate.engine.endLoadingCollections()
>>>>>>>> method - it has following code:
>>>>>>>>
>>>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>>>> resultSetCollections.size();
>>>>>>>>
>>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>>> log.debug( count + " collections were found in
>>>>>>>> result set for role: " + persister.getRole() );
>>>>>>>> }
>>>>>>>>
>>>>>>>> //now finish them
>>>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>>>> LoadingCollectionEntry lce =
>>>>>>>> (LoadingCollectionEntry) resultSetCollections.get(i);
>>>>>>>> endLoadingCollection(lce, persister, em);
>>>>>>>> }
>>>>>>>>
>>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>>> log.debug( count + " collections initialized for
>>>>>>>> role: " + persister.getRole() );
>>>>>>>> }
>>>>>>>>
>>>>>>>> In my example count = 3. So THREE PersistentBags were loaded -
>>>>>>>> it happened because my association has fetch="subselect".
>>>>>>>>
>>>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>>>
>>>>>>>> Why other were not added?
>>>>>>>>
>>>>>>>> Answer is simple:
>>>>>>>> Method doLoad() was not called for two other
>>>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>>>> is in this method. Why was notthis method called to two other
>>>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>>>
>>>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>>>
>>>>>>>> public boolean isLoaded() {
>>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>>> if (((AbstractPersistentCollection)
>>>>>>>> delegate).wasInitialized()) {
>>>>>>>> setIsLoaded(true);
>>>>>>>> // log.debug("Persistentlist already
>>>>>>>> initialized, probably eagerly loaded: " + getLogString());
>>>>>>>> }
>>>>>>>> }
>>>>>>>> return super.isLoaded();
>>>>>>>> }
>>>>>>>>
>>>>>>>> So let me describe full chain of events:
>>>>>>>>
>>>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>>>> fetch="subselect". When one of HibernatePersistableELists is
>>>>>>>> asked for collection it force hibernate to load this collection via
>>>>>>>>
>>>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>>>
>>>>>>>> and adds objects to resource.
>>>>>>>>
>>>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>>>
>>>>>>>> public boolean isLoaded() {
>>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>>> if (((AbstractPersistentCollection)
>>>>>>>> delegate).wasInitialized()) {
>>>>>>>> setIsLoaded(true);
>>>>>>>> // log.debug("Persistentlist already
>>>>>>>> initialized, probably eagerly loaded: " + getLogString());
>>>>>>>> }
>>>>>>>> }
>>>>>>>> return super.isLoaded();
>>>>>>>> }
>>>>>>>>
>>>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>>>
>>>>>>>> This happens when fetch="subselect". Details of how
>>>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>>>
>>>>>>>> My proposals:
>>>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>>>> check that objects are added - then isLoaded needs to be
>>>>>>>> implemented like:
>>>>>>>>
>>>>>>>> public boolean isLoaded() {
>>>>>>>> if (isLoaded){
>>>>>>>> return true;
>>>>>>>> }
>>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>>> if (((AbstractPersistentCollection)
>>>>>>>> delegate).wasInitialized()) {
>>>>>>>> setIsLoaded(true);
>>>>>>>> // log.debug("Persistentlist already
>>>>>>>> initialized, probably eagerly loaded: " + getLogString());
>>>>>>>> }
>>>>>>>> }
>>>>>>>> return super.isLoaded();
>>>>>>>> }
>>>>>>>>
>>>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>>>
>>>>>>>> Ilya
>>>>>>>>
>>>>>>>> Martin Taal wrote:
>>>>>>>>> I do not fully understand what happens here. Can you describe
>>>>>>>>> the case/example in which this occurs (automatically loading
>>>>>>>>> other such collections)? The hibernate behavior as you describe
>>>>>>>>> it is unfamiliar to me.
>>>>>>>>>
>>>>>>>>> gr. Martin
>>>>>>>>>
>>>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>>>> When I use HibernateResource with loading strategy
>>>>>>>>>> addToContents then all is OK until I have created association
>>>>>>>>>> with fetch="subselect".
>>>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>>>> loaded they are not added to resource.
>>>>>>>>>>
>>>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>>>> ONE such collection BUT if there are any other such
>>>>>>>>>> collections that are not loaded Hibernate can load all such
>>>>>>>>>> collections. And fact of loading of other collections are not
>>>>>>>>>> caught by Teneo.
>>>>>>>>>>
>>>>>>>>>> Is this a bug?
>>>>>>>>>>
>>>>>>>>>> Thanks
>>>>>>>>>>
>>>>>>>>>> Ilya
>>>>>>>>>
>>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
| |
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600267 is a reply to message #65598] |
Wed, 27 December 2006 13:10 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Hi Martin
I suppose that these details help you to understand problem:
This is stack trace:
Thread [main] (Suspended (breakpoint at line 366 in
AbstractPersistentCollection))
PersistentBag(AbstractPersistentCollection).setInitialized() line: 366
PersistentBag(AbstractPersistentCollection).afterInitialize( ) line: 319
PersistentBag(AbstractPersistentCollection).endRead() line: 315
CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
CollectionPersister, EntityMode) line: 183
CollectionLoadContext.endLoadingCollections(CollectionPersis ter, List,
EntityMode) line: 268
CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
Object, SessionImplementor) line: 249
SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
SessionImplementor, CollectionPersister) line: 866
SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
Object, SessionImplementor, boolean) line: 853
SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
QueryParameters, boolean) line: 717
SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
QueryParameters, boolean) line: 224
SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
Serializable[], Object[], Type[], Map, Type) line: 1990
SubselectOneToManyLoader.initialize(Serializable, SessionImplementor)
line: 58
OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
SessionImplementor) line: 565
DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
line: 60
SessionImpl.initializeCollection(PersistentCollection, boolean) line: 1716
PersistentBag(AbstractPersistentCollection).initialize(boole an) line: 344
PersistentBag(AbstractPersistentCollection).read() line: 86
PersistentBag.toArray() line: 257
HibernatePersistableEList.doLoad() line: 106
HibernatePersistableEList(PersistableEList).load() line: 187
HibernatePersistableEList(PersistableEList).delegateSize() line: 395
HibernatePersistableEList(DelegatingEList).size() line: 214
DelegatingEList$EIterator.hasNext() line: 1000
DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
line: 339
DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
line: 380
As you see activity begins with: HibernatePersistableEList.doLoad()
line: 106
and PersistentBag is marked as initialized BUT: request was passed to
EXACTLY ONE HibernatePersistableEList - so after PersistentBag
corresponding to THIS HibernatePersistableEList was loaded all objects
contained in PersistentBag are added to resource - it's OK.
PROBLEM:
Actually in my example THREE PersistentBag were loaded - cause three
object with such lazy collections are already loaded - try to
investigate org.hibernate.engine.endLoadingCollections() method - it has
following code:
final int count = (resultSetCollections == null) ? 0 :
resultSetCollections.size();
if ( log.isDebugEnabled() ) {
log.debug( count + " collections were found in result set for role: "
+ persister.getRole() );
}
//now finish them
for ( int i = 0; i < count; i++ ) {
LoadingCollectionEntry lce = (LoadingCollectionEntry)
resultSetCollections.get(i);
endLoadingCollection(lce, persister, em);
}
if ( log.isDebugEnabled() ) {
log.debug( count + " collections initialized for role: " +
persister.getRole() );
}
In my example count = 3. So THREE PersistentBags were loaded - it
happened because my association has fetch="subselect".
So THREE PersistentBags were were marked as initialized but ONLY object
from ONE OF THEM were added to contents of resource.
Why other were not added?
Answer is simple:
Method doLoad() was not called for two other HibernatePersistableEList.
Adding objects to resource.contents() is in this method. Why was notthis
method called to two other list? Cause it is called only if isLoaded()
returns false.
BUT HOW is this method implemented for HibernatePersistableEList?
public boolean isLoaded() {
if (delegate instanceof AbstractPersistentCollection) {
if (((AbstractPersistentCollection) delegate).wasInitialized()) {
setIsLoaded(true);
// log.debug("Persistentlist already initialized, probably eagerly
loaded: " + getLogString());
}
}
return super.isLoaded();
}
So let me describe full chain of events:
There are THREE objects with lazy not loaded collections with
fetch="subselect". When one of HibernatePersistableELists is asked for
collection it force hibernate to load this collection via
Object[] objs = delegate.toArray(); // this forces the load
and adds objects to resource.
BUT during forcing of loading one delegate two other delegates were
loaded too - they were marked as initialized. So two other
HibernatePersistableELists will return isLoaded() = true because:
public boolean isLoaded() {
if (delegate instanceof AbstractPersistentCollection) {
if (((AbstractPersistentCollection) delegate).wasInitialized()) {
setIsLoaded(true);
// log.debug("Persistentlist already initialized, probably eagerly
loaded: " + getLogString());
}
}
return super.isLoaded();
}
So Teneo looses the moment when delegate is really initialized.
This happens when fetch="subselect". Details of how fetch="subselect"
works are in hibernate docs.
My proposals:
You can override setIsLoaded() in HibernatePersistableELists and check
that objects are added - then isLoaded needs to be implemented like:
public boolean isLoaded() {
if (isLoaded){
return true;
}
if (delegate instanceof AbstractPersistentCollection) {
if (((AbstractPersistentCollection) delegate).wasInitialized()) {
setIsLoaded(true);
// log.debug("Persistentlist already initialized, probably eagerly
loaded: " + getLogString());
}
}
return super.isLoaded();
}
Feel free to ask me for more details if my answer is not enough.
Ilya
Martin Taal wrote:
> I do not fully understand what happens here. Can you describe the
> case/example in which this occurs (automatically loading other such
> collections)? The hibernate behavior as you describe it is unfamiliar to
> me.
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> When I use HibernateResource with loading strategy addToContents then
>> all is OK until I have created association with fetch="subselect".
>> Sometimes objects that are inside these lazy collections are loaded
>> they are not added to resource.
>>
>> As far as I understand it happens when I ask some objects from ONE
>> such collection BUT if there are any other such collections that are
>> not loaded Hibernate can load all such collections. And fact of
>> loading of other collections are not caught by Teneo.
>>
>> Is this a bug?
>>
>> Thanks
>>
>> Ilya
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600275 is a reply to message #65619] |
Wed, 27 December 2006 13:13 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Sorry - I misprinted method name where ALL INTERESTING happens:
org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
instead of org.hibernate.engine.endLoadingCollections()
Ilya
Ilya Klyuchnikov wrote:
> Hi Martin
>
> I suppose that these details help you to understand problem:
>
> This is stack trace:
>
> Thread [main] (Suspended (breakpoint at line 366 in
> AbstractPersistentCollection))
> PersistentBag(AbstractPersistentCollection).setInitialized() line:
> 366
> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
> 319
> PersistentBag(AbstractPersistentCollection).endRead() line: 315
> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
> CollectionPersister, EntityMode) line: 183
> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
> List, EntityMode) line: 268
> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
> Object, SessionImplementor) line: 249
> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
> SessionImplementor, CollectionPersister) line: 866
> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
> Object, SessionImplementor, boolean) line: 853
> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
> QueryParameters, boolean) line: 717
> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
> QueryParameters, boolean) line: 224
> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
> Serializable[], Object[], Type[], Map, Type) line: 1990
> SubselectOneToManyLoader.initialize(Serializable,
> SessionImplementor) line: 58
> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
> SessionImplementor) line: 565
> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
> line: 60
> SessionImpl.initializeCollection(PersistentCollection, boolean)
> line: 1716
> PersistentBag(AbstractPersistentCollection).initialize(boole an)
> line: 344
> PersistentBag(AbstractPersistentCollection).read() line: 86
> PersistentBag.toArray() line: 257
> HibernatePersistableEList.doLoad() line: 106
> HibernatePersistableEList(PersistableEList).load() line: 187
> HibernatePersistableEList(PersistableEList).delegateSize() line: 395
> HibernatePersistableEList(DelegatingEList).size() line: 214
> DelegatingEList$EIterator.hasNext() line: 1000
> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
> line: 339
> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
> line: 380
>
> As you see activity begins with: HibernatePersistableEList.doLoad()
> line: 106
>
> and PersistentBag is marked as initialized BUT: request was passed to
> EXACTLY ONE HibernatePersistableEList - so after PersistentBag
> corresponding to THIS HibernatePersistableEList was loaded all objects
> contained in PersistentBag are added to resource - it's OK.
>
> PROBLEM:
>
> Actually in my example THREE PersistentBag were loaded - cause three
> object with such lazy collections are already loaded - try to
> investigate org.hibernate.engine.endLoadingCollections() method - it has
> following code:
>
> final int count = (resultSetCollections == null) ? 0 :
> resultSetCollections.size();
>
> if ( log.isDebugEnabled() ) {
> log.debug( count + " collections were found in result set
> for role: " + persister.getRole() );
> }
>
> //now finish them
> for ( int i = 0; i < count; i++ ) {
> LoadingCollectionEntry lce = (LoadingCollectionEntry)
> resultSetCollections.get(i);
> endLoadingCollection(lce, persister, em);
> }
>
> if ( log.isDebugEnabled() ) {
> log.debug( count + " collections initialized for role: " +
> persister.getRole() );
> }
>
> In my example count = 3. So THREE PersistentBags were loaded - it
> happened because my association has fetch="subselect".
>
> So THREE PersistentBags were were marked as initialized but ONLY object
> from ONE OF THEM were added to contents of resource.
>
> Why other were not added?
>
> Answer is simple:
> Method doLoad() was not called for two other HibernatePersistableEList.
> Adding objects to resource.contents() is in this method. Why was notthis
> method called to two other list? Cause it is called only if isLoaded()
> returns false.
>
> BUT HOW is this method implemented for HibernatePersistableEList?
>
> public boolean isLoaded() {
> if (delegate instanceof AbstractPersistentCollection) {
> if (((AbstractPersistentCollection)
> delegate).wasInitialized()) {
> setIsLoaded(true);
> // log.debug("Persistentlist already initialized,
> probably eagerly loaded: " + getLogString());
> }
> }
> return super.isLoaded();
> }
>
> So let me describe full chain of events:
>
> There are THREE objects with lazy not loaded collections with
> fetch="subselect". When one of HibernatePersistableELists is asked for
> collection it force hibernate to load this collection via
>
> Object[] objs = delegate.toArray(); // this forces the load
>
> and adds objects to resource.
>
> BUT during forcing of loading one delegate two other delegates were
> loaded too - they were marked as initialized. So two other
> HibernatePersistableELists will return isLoaded() = true because:
>
> public boolean isLoaded() {
> if (delegate instanceof AbstractPersistentCollection) {
> if (((AbstractPersistentCollection)
> delegate).wasInitialized()) {
> setIsLoaded(true);
> // log.debug("Persistentlist already initialized,
> probably eagerly loaded: " + getLogString());
> }
> }
> return super.isLoaded();
> }
>
> So Teneo looses the moment when delegate is really initialized.
>
> This happens when fetch="subselect". Details of how fetch="subselect"
> works are in hibernate docs.
>
> My proposals:
> You can override setIsLoaded() in HibernatePersistableELists and check
> that objects are added - then isLoaded needs to be implemented like:
>
> public boolean isLoaded() {
> if (isLoaded){
> return true;
> }
> if (delegate instanceof AbstractPersistentCollection) {
> if (((AbstractPersistentCollection)
> delegate).wasInitialized()) {
> setIsLoaded(true);
> // log.debug("Persistentlist already initialized,
> probably eagerly loaded: " + getLogString());
> }
> }
> return super.isLoaded();
> }
>
> Feel free to ask me for more details if my answer is not enough.
>
> Ilya
>
> Martin Taal wrote:
>> I do not fully understand what happens here. Can you describe the
>> case/example in which this occurs (automatically loading other such
>> collections)? The hibernate behavior as you describe it is unfamiliar
>> to me.
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> When I use HibernateResource with loading strategy addToContents then
>>> all is OK until I have created association with fetch="subselect".
>>> Sometimes objects that are inside these lazy collections are loaded
>>> they are not added to resource.
>>>
>>> As far as I understand it happens when I ask some objects from ONE
>>> such collection BUT if there are any other such collections that are
>>> not loaded Hibernate can load all such collections. And fact of
>>> loading of other collections are not caught by Teneo.
>>>
>>> Is this a bug?
>>>
>>> Thanks
>>>
>>> Ilya
>>
>>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600281 is a reply to message #65639] |
Wed, 27 December 2006 13:48 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Hi Ilya,
Yes the solution is in the isLoaded method. If the underlying hibernate collection is already
loaded/initialized while isLoaded=false then the children need to be added to the resource (calling
doLoad with some extra handling should work).
Are the automatically loaded collections eager or lazy?
gr. Martin
Ilya Klyuchnikov wrote:
> Sorry - I misprinted method name where ALL INTERESTING happens:
>
> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
> instead of org.hibernate.engine.endLoadingCollections()
>
> Ilya
>
> Ilya Klyuchnikov wrote:
>> Hi Martin
>>
>> I suppose that these details help you to understand problem:
>>
>> This is stack trace:
>>
>> Thread [main] (Suspended (breakpoint at line 366 in
>> AbstractPersistentCollection))
>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>> 366
>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>> 319 PersistentBag(AbstractPersistentCollection).endRead() line:
>> 315
>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>> CollectionPersister, EntityMode) line: 183
>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter, List,
>> EntityMode) line: 268
>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>> Object, SessionImplementor) line: 249
>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>> SessionImplementor, CollectionPersister) line: 866
>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>> Object, SessionImplementor, boolean) line: 853
>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>> QueryParameters, boolean) line: 717
>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>> QueryParameters, boolean) line: 224
>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>> Serializable[], Object[], Type[], Map, Type) line: 1990
>> SubselectOneToManyLoader.initialize(Serializable, SessionImplementor)
>> line: 58
>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>> SessionImplementor) line: 565
>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>> line: 60 SessionImpl.initializeCollection(PersistentCollection,
>> boolean) line: 1716
>> PersistentBag(AbstractPersistentCollection).initialize(boole an) line:
>> 344 PersistentBag(AbstractPersistentCollection).read() line:
>> 86 PersistentBag.toArray() line: 257
>> HibernatePersistableEList.doLoad() line: 106
>> HibernatePersistableEList(PersistableEList).load() line: 187
>> HibernatePersistableEList(PersistableEList).delegateSize() line: 395
>> HibernatePersistableEList(DelegatingEList).size() line: 214
>> DelegatingEList$EIterator.hasNext() line: 1000
>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>> line: 339
>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>> line: 380 As you see activity begins with:
>> HibernatePersistableEList.doLoad() line: 106
>>
>> and PersistentBag is marked as initialized BUT: request was passed to
>> EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>> corresponding to THIS HibernatePersistableEList was loaded all objects
>> contained in PersistentBag are added to resource - it's OK.
>>
>> PROBLEM:
>>
>> Actually in my example THREE PersistentBag were loaded - cause three
>> object with such lazy collections are already loaded - try to
>> investigate org.hibernate.engine.endLoadingCollections() method - it
>> has following code:
>>
>> final int count = (resultSetCollections == null) ? 0 :
>> resultSetCollections.size();
>>
>> if ( log.isDebugEnabled() ) {
>> log.debug( count + " collections were found in result set
>> for role: " + persister.getRole() );
>> }
>>
>> //now finish them
>> for ( int i = 0; i < count; i++ ) {
>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>> resultSetCollections.get(i);
>> endLoadingCollection(lce, persister, em);
>> }
>>
>> if ( log.isDebugEnabled() ) {
>> log.debug( count + " collections initialized for role: " +
>> persister.getRole() );
>> }
>>
>> In my example count = 3. So THREE PersistentBags were loaded - it
>> happened because my association has fetch="subselect".
>>
>> So THREE PersistentBags were were marked as initialized but ONLY
>> object from ONE OF THEM were added to contents of resource.
>>
>> Why other were not added?
>>
>> Answer is simple:
>> Method doLoad() was not called for two other
>> HibernatePersistableEList. Adding objects to resource.contents() is in
>> this method. Why was notthis method called to two other list? Cause it
>> is called only if isLoaded() returns false.
>>
>> BUT HOW is this method implemented for HibernatePersistableEList?
>>
>> public boolean isLoaded() {
>> if (delegate instanceof AbstractPersistentCollection) {
>> if (((AbstractPersistentCollection)
>> delegate).wasInitialized()) {
>> setIsLoaded(true);
>> // log.debug("Persistentlist already initialized,
>> probably eagerly loaded: " + getLogString());
>> }
>> }
>> return super.isLoaded();
>> }
>>
>> So let me describe full chain of events:
>>
>> There are THREE objects with lazy not loaded collections with
>> fetch="subselect". When one of HibernatePersistableELists is asked for
>> collection it force hibernate to load this collection via
>>
>> Object[] objs = delegate.toArray(); // this forces the load
>>
>> and adds objects to resource.
>>
>> BUT during forcing of loading one delegate two other delegates were
>> loaded too - they were marked as initialized. So two other
>> HibernatePersistableELists will return isLoaded() = true because:
>>
>> public boolean isLoaded() {
>> if (delegate instanceof AbstractPersistentCollection) {
>> if (((AbstractPersistentCollection)
>> delegate).wasInitialized()) {
>> setIsLoaded(true);
>> // log.debug("Persistentlist already initialized,
>> probably eagerly loaded: " + getLogString());
>> }
>> }
>> return super.isLoaded();
>> }
>>
>> So Teneo looses the moment when delegate is really initialized.
>>
>> This happens when fetch="subselect". Details of how fetch="subselect"
>> works are in hibernate docs.
>>
>> My proposals:
>> You can override setIsLoaded() in HibernatePersistableELists and check
>> that objects are added - then isLoaded needs to be implemented like:
>>
>> public boolean isLoaded() {
>> if (isLoaded){
>> return true;
>> }
>> if (delegate instanceof AbstractPersistentCollection) {
>> if (((AbstractPersistentCollection)
>> delegate).wasInitialized()) {
>> setIsLoaded(true);
>> // log.debug("Persistentlist already initialized,
>> probably eagerly loaded: " + getLogString());
>> }
>> }
>> return super.isLoaded();
>> }
>>
>> Feel free to ask me for more details if my answer is not enough.
>>
>> Ilya
>>
>> Martin Taal wrote:
>>> I do not fully understand what happens here. Can you describe the
>>> case/example in which this occurs (automatically loading other such
>>> collections)? The hibernate behavior as you describe it is unfamiliar
>>> to me.
>>>
>>> gr. Martin
>>>
>>> Ilya Klyuchnikov wrote:
>>>> When I use HibernateResource with loading strategy addToContents
>>>> then all is OK until I have created association with fetch="subselect".
>>>> Sometimes objects that are inside these lazy collections are loaded
>>>> they are not added to resource.
>>>>
>>>> As far as I understand it happens when I ask some objects from ONE
>>>> such collection BUT if there are any other such collections that are
>>>> not loaded Hibernate can load all such collections. And fact of
>>>> loading of other collections are not caught by Teneo.
>>>>
>>>> Is this a bug?
>>>>
>>>> Thanks
>>>>
>>>> Ilya
>>>
>>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600287 is a reply to message #65661] |
Wed, 27 December 2006 13:54 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
In my example lazy="true".
BTW, if there are collections with lazy="false" then during resource
loading objects in such collections are not added to resource.
Martin Taal wrote:
> Hi Ilya,
> Yes the solution is in the isLoaded method. If the underlying hibernate
> collection is already loaded/initialized while isLoaded=false then the
> children need to be added to the resource (calling doLoad with some
> extra handling should work).
>
> Are the automatically loaded collections eager or lazy?
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>
>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>> instead of org.hibernate.engine.endLoadingCollections()
>>
>> Ilya
>>
>> Ilya Klyuchnikov wrote:
>>> Hi Martin
>>>
>>> I suppose that these details help you to understand problem:
>>>
>>> This is stack trace:
>>>
>>> Thread [main] (Suspended (breakpoint at line 366 in
>>> AbstractPersistentCollection))
>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>> 366
>>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>>> 319 PersistentBag(AbstractPersistentCollection).endRead() line:
>>> 315
>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>> CollectionPersister, EntityMode) line: 183
>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>> List, EntityMode) line: 268
>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>> Object, SessionImplementor) line: 249
>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>> SessionImplementor, CollectionPersister) line: 866
>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>> Object, SessionImplementor, boolean) line: 853
>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>> QueryParameters, boolean) line: 717
>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>> QueryParameters, boolean) line: 224
>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>> SubselectOneToManyLoader.initialize(Serializable, SessionImplementor)
>>> line: 58
>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>> SessionImplementor) line: 565
>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>> line: 60 SessionImpl.initializeCollection(PersistentCollection,
>>> boolean) line: 1716
>>> PersistentBag(AbstractPersistentCollection).initialize(boole an) line:
>>> 344 PersistentBag(AbstractPersistentCollection).read() line:
>>> 86 PersistentBag.toArray() line: 257
>>> HibernatePersistableEList.doLoad() line: 106
>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>> line: 339
>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>> line: 380 As you see activity begins with:
>>> HibernatePersistableEList.doLoad() line: 106
>>>
>>> and PersistentBag is marked as initialized BUT: request was passed to
>>> EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>> corresponding to THIS HibernatePersistableEList was loaded all
>>> objects contained in PersistentBag are added to resource - it's OK.
>>>
>>> PROBLEM:
>>>
>>> Actually in my example THREE PersistentBag were loaded - cause three
>>> object with such lazy collections are already loaded - try to
>>> investigate org.hibernate.engine.endLoadingCollections() method - it
>>> has following code:
>>>
>>> final int count = (resultSetCollections == null) ? 0 :
>>> resultSetCollections.size();
>>>
>>> if ( log.isDebugEnabled() ) {
>>> log.debug( count + " collections were found in result set
>>> for role: " + persister.getRole() );
>>> }
>>>
>>> //now finish them
>>> for ( int i = 0; i < count; i++ ) {
>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>> resultSetCollections.get(i);
>>> endLoadingCollection(lce, persister, em);
>>> }
>>>
>>> if ( log.isDebugEnabled() ) {
>>> log.debug( count + " collections initialized for role: "
>>> + persister.getRole() );
>>> }
>>>
>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>> happened because my association has fetch="subselect".
>>>
>>> So THREE PersistentBags were were marked as initialized but ONLY
>>> object from ONE OF THEM were added to contents of resource.
>>>
>>> Why other were not added?
>>>
>>> Answer is simple:
>>> Method doLoad() was not called for two other
>>> HibernatePersistableEList. Adding objects to resource.contents() is
>>> in this method. Why was notthis method called to two other list?
>>> Cause it is called only if isLoaded() returns false.
>>>
>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>
>>> public boolean isLoaded() {
>>> if (delegate instanceof AbstractPersistentCollection) {
>>> if (((AbstractPersistentCollection)
>>> delegate).wasInitialized()) {
>>> setIsLoaded(true);
>>> // log.debug("Persistentlist already initialized,
>>> probably eagerly loaded: " + getLogString());
>>> }
>>> }
>>> return super.isLoaded();
>>> }
>>>
>>> So let me describe full chain of events:
>>>
>>> There are THREE objects with lazy not loaded collections with
>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>> for collection it force hibernate to load this collection via
>>>
>>> Object[] objs = delegate.toArray(); // this forces the load
>>>
>>> and adds objects to resource.
>>>
>>> BUT during forcing of loading one delegate two other delegates were
>>> loaded too - they were marked as initialized. So two other
>>> HibernatePersistableELists will return isLoaded() = true because:
>>>
>>> public boolean isLoaded() {
>>> if (delegate instanceof AbstractPersistentCollection) {
>>> if (((AbstractPersistentCollection)
>>> delegate).wasInitialized()) {
>>> setIsLoaded(true);
>>> // log.debug("Persistentlist already initialized,
>>> probably eagerly loaded: " + getLogString());
>>> }
>>> }
>>> return super.isLoaded();
>>> }
>>>
>>> So Teneo looses the moment when delegate is really initialized.
>>>
>>> This happens when fetch="subselect". Details of how fetch="subselect"
>>> works are in hibernate docs.
>>>
>>> My proposals:
>>> You can override setIsLoaded() in HibernatePersistableELists and
>>> check that objects are added - then isLoaded needs to be implemented
>>> like:
>>>
>>> public boolean isLoaded() {
>>> if (isLoaded){
>>> return true;
>>> }
>>> if (delegate instanceof AbstractPersistentCollection) {
>>> if (((AbstractPersistentCollection)
>>> delegate).wasInitialized()) {
>>> setIsLoaded(true);
>>> // log.debug("Persistentlist already initialized,
>>> probably eagerly loaded: " + getLogString());
>>> }
>>> }
>>> return super.isLoaded();
>>> }
>>>
>>> Feel free to ask me for more details if my answer is not enough.
>>>
>>> Ilya
>>>
>>> Martin Taal wrote:
>>>> I do not fully understand what happens here. Can you describe the
>>>> case/example in which this occurs (automatically loading other such
>>>> collections)? The hibernate behavior as you describe it is
>>>> unfamiliar to me.
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> When I use HibernateResource with loading strategy addToContents
>>>>> then all is OK until I have created association with
>>>>> fetch="subselect".
>>>>> Sometimes objects that are inside these lazy collections are loaded
>>>>> they are not added to resource.
>>>>>
>>>>> As far as I understand it happens when I ask some objects from ONE
>>>>> such collection BUT if there are any other such collections that
>>>>> are not loaded Hibernate can load all such collections. And fact of
>>>>> loading of other collections are not caught by Teneo.
>>>>>
>>>>> Is this a bug?
>>>>>
>>>>> Thanks
>>>>>
>>>>> Ilya
>>>>
>>>>
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600292 is a reply to message #65683] |
Wed, 27 December 2006 14:10 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Yes for eagerly loaded lists I understand the issue. What I don't understand is why the lazy loaded
collections are loaded (automatically). You say:
>>>> Actually in my example THREE PersistentBag were loaded - cause three
>>>> object with such lazy collections are already loaded
What do you mean?
gr. Martin
Ilya Klyuchnikov wrote:
> In my example lazy="true".
>
> BTW, if there are collections with lazy="false" then during resource
> loading objects in such collections are not added to resource.
>
> Martin Taal wrote:
>> Hi Ilya,
>> Yes the solution is in the isLoaded method. If the underlying
>> hibernate collection is already loaded/initialized while
>> isLoaded=false then the children need to be added to the resource
>> (calling doLoad with some extra handling should work).
>>
>> Are the automatically loaded collections eager or lazy?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>
>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>> instead of org.hibernate.engine.endLoadingCollections()
>>>
>>> Ilya
>>>
>>> Ilya Klyuchnikov wrote:
>>>> Hi Martin
>>>>
>>>> I suppose that these details help you to understand problem:
>>>>
>>>> This is stack trace:
>>>>
>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>> AbstractPersistentCollection))
>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>> 366
>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>>>> 319 PersistentBag(AbstractPersistentCollection).endRead()
>>>> line: 315
>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>> CollectionPersister, EntityMode) line: 183
>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>> List, EntityMode) line: 268
>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>> Object, SessionImplementor) line: 249
>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>> SessionImplementor, CollectionPersister) line: 866
>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>> Object, SessionImplementor, boolean) line: 853
>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>> QueryParameters, boolean) line: 717
>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>> QueryParameters, boolean) line: 224
>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>> SessionImplementor) line: 58
>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>> SessionImplementor) line: 565
>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>> line: 60
>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>> line: 1716
>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>> line: 86 PersistentBag.toArray() line: 257
>>>> HibernatePersistableEList.doLoad() line: 106
>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>> line: 339
>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>> line: 380 As you see activity begins with:
>>>> HibernatePersistableEList.doLoad() line: 106
>>>>
>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>
>>>> PROBLEM:
>>>>
>>>> Actually in my example THREE PersistentBag were loaded - cause three
>>>> object with such lazy collections are already loaded - try to
>>>> investigate org.hibernate.engine.endLoadingCollections() method - it
>>>> has following code:
>>>>
>>>> final int count = (resultSetCollections == null) ? 0 :
>>>> resultSetCollections.size();
>>>>
>>>> if ( log.isDebugEnabled() ) {
>>>> log.debug( count + " collections were found in result
>>>> set for role: " + persister.getRole() );
>>>> }
>>>>
>>>> //now finish them
>>>> for ( int i = 0; i < count; i++ ) {
>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>> resultSetCollections.get(i);
>>>> endLoadingCollection(lce, persister, em);
>>>> }
>>>>
>>>> if ( log.isDebugEnabled() ) {
>>>> log.debug( count + " collections initialized for role: "
>>>> + persister.getRole() );
>>>> }
>>>>
>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>> happened because my association has fetch="subselect".
>>>>
>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>> object from ONE OF THEM were added to contents of resource.
>>>>
>>>> Why other were not added?
>>>>
>>>> Answer is simple:
>>>> Method doLoad() was not called for two other
>>>> HibernatePersistableEList. Adding objects to resource.contents() is
>>>> in this method. Why was notthis method called to two other list?
>>>> Cause it is called only if isLoaded() returns false.
>>>>
>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>
>>>> public boolean isLoaded() {
>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>> if (((AbstractPersistentCollection)
>>>> delegate).wasInitialized()) {
>>>> setIsLoaded(true);
>>>> // log.debug("Persistentlist already initialized,
>>>> probably eagerly loaded: " + getLogString());
>>>> }
>>>> }
>>>> return super.isLoaded();
>>>> }
>>>>
>>>> So let me describe full chain of events:
>>>>
>>>> There are THREE objects with lazy not loaded collections with
>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>> for collection it force hibernate to load this collection via
>>>>
>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>
>>>> and adds objects to resource.
>>>>
>>>> BUT during forcing of loading one delegate two other delegates were
>>>> loaded too - they were marked as initialized. So two other
>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>
>>>> public boolean isLoaded() {
>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>> if (((AbstractPersistentCollection)
>>>> delegate).wasInitialized()) {
>>>> setIsLoaded(true);
>>>> // log.debug("Persistentlist already initialized,
>>>> probably eagerly loaded: " + getLogString());
>>>> }
>>>> }
>>>> return super.isLoaded();
>>>> }
>>>>
>>>> So Teneo looses the moment when delegate is really initialized.
>>>>
>>>> This happens when fetch="subselect". Details of how
>>>> fetch="subselect" works are in hibernate docs.
>>>>
>>>> My proposals:
>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>> check that objects are added - then isLoaded needs to be implemented
>>>> like:
>>>>
>>>> public boolean isLoaded() {
>>>> if (isLoaded){
>>>> return true;
>>>> }
>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>> if (((AbstractPersistentCollection)
>>>> delegate).wasInitialized()) {
>>>> setIsLoaded(true);
>>>> // log.debug("Persistentlist already initialized,
>>>> probably eagerly loaded: " + getLogString());
>>>> }
>>>> }
>>>> return super.isLoaded();
>>>> }
>>>>
>>>> Feel free to ask me for more details if my answer is not enough.
>>>>
>>>> Ilya
>>>>
>>>> Martin Taal wrote:
>>>>> I do not fully understand what happens here. Can you describe the
>>>>> case/example in which this occurs (automatically loading other such
>>>>> collections)? The hibernate behavior as you describe it is
>>>>> unfamiliar to me.
>>>>>
>>>>> gr. Martin
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>> then all is OK until I have created association with
>>>>>> fetch="subselect".
>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>> loaded they are not added to resource.
>>>>>>
>>>>>> As far as I understand it happens when I ask some objects from ONE
>>>>>> such collection BUT if there are any other such collections that
>>>>>> are not loaded Hibernate can load all such collections. And fact
>>>>>> of loading of other collections are not caught by Teneo.
>>>>>>
>>>>>> Is this a bug?
>>>>>>
>>>>>> Thanks
>>>>>>
>>>>>> Ilya
>>>>>
>>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600322 is a reply to message #65705] |
Wed, 27 December 2006 14:25 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
The reason that fetch="subselect":
With fetch="subselect" Hibernate loads ALL such collections on demand.
In my example when I ask DeploymentEnvironment.getDomains() Hibernate
generates such query:
Hibernate: select domain0_.`environment_id` as environm6_1_,
domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_, domain0_.e_version
as e3_21_0_, domain0_.`name` as name4_21_0_, domain0_.`modified` as
modified5_21_0_, domain0_.`environment_id` as environm6_21_0_ from
`domain` domain0_ where domain0_.`environment_id` in (select
deployment1_.`id` from environment_deploys deploysto0_ left outer join
`environment` deployment1_ on deploysto0_.`from_id`=deployment1_.`id`
where deploysto0_.`to_id`=?)
Put attentions to where domain0_.`environment_id` in ...
So this is a feature of Hibernate:
If there are some not loaded collection corresponding to the same
association (DeploymentEnvironment.domains in my example) having
fetch="subselect" and client ask ONE of these collections to be loaded
then Hibernate loads ALL collections. You can see this logic in
AbstractCollectionPersister class.
See
http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
for details.
Ilya
Martin Taal wrote:
> Yes for eagerly loaded lists I understand the issue. What I don't
> understand is why the lazy loaded collections are loaded
> (automatically). You say:
> >>>> Actually in my example THREE PersistentBag were loaded - cause three
> >>>> object with such lazy collections are already loaded
>
> What do you mean?
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> In my example lazy="true".
>>
>> BTW, if there are collections with lazy="false" then during resource
>> loading objects in such collections are not added to resource.
>>
>> Martin Taal wrote:
>>> Hi Ilya,
>>> Yes the solution is in the isLoaded method. If the underlying
>>> hibernate collection is already loaded/initialized while
>>> isLoaded=false then the children need to be added to the resource
>>> (calling doLoad with some extra handling should work).
>>>
>>> Are the automatically loaded collections eager or lazy?
>>>
>>> gr. Martin
>>>
>>> Ilya Klyuchnikov wrote:
>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>
>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>
>>>> Ilya
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> Hi Martin
>>>>>
>>>>> I suppose that these details help you to understand problem:
>>>>>
>>>>> This is stack trace:
>>>>>
>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>> AbstractPersistentCollection))
>>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>>> 366
>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( ) line:
>>>>> 319 PersistentBag(AbstractPersistentCollection).endRead()
>>>>> line: 315
>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>> CollectionPersister, EntityMode) line: 183
>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>> List, EntityMode) line: 268
>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>> Object, SessionImplementor) line: 249
>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>> Object, SessionImplementor, boolean) line: 853
>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>> QueryParameters, boolean) line: 717
>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>> QueryParameters, boolean) line: 224
>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>> SessionImplementor) line: 58
>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>> SessionImplementor) line: 565
>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>> line: 60
>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>> line: 1716
>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>>> line: 86 PersistentBag.toArray() line: 257
>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>> line: 339
>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>> line: 380 As you see activity begins with:
>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>
>>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>>
>>>>> PROBLEM:
>>>>>
>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>> three object with such lazy collections are already loaded - try to
>>>>> investigate org.hibernate.engine.endLoadingCollections() method -
>>>>> it has following code:
>>>>>
>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>> resultSetCollections.size();
>>>>>
>>>>> if ( log.isDebugEnabled() ) {
>>>>> log.debug( count + " collections were found in result
>>>>> set for role: " + persister.getRole() );
>>>>> }
>>>>>
>>>>> //now finish them
>>>>> for ( int i = 0; i < count; i++ ) {
>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>> resultSetCollections.get(i);
>>>>> endLoadingCollection(lce, persister, em);
>>>>> }
>>>>>
>>>>> if ( log.isDebugEnabled() ) {
>>>>> log.debug( count + " collections initialized for role:
>>>>> " + persister.getRole() );
>>>>> }
>>>>>
>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>> happened because my association has fetch="subselect".
>>>>>
>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>
>>>>> Why other were not added?
>>>>>
>>>>> Answer is simple:
>>>>> Method doLoad() was not called for two other
>>>>> HibernatePersistableEList. Adding objects to resource.contents() is
>>>>> in this method. Why was notthis method called to two other list?
>>>>> Cause it is called only if isLoaded() returns false.
>>>>>
>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>
>>>>> public boolean isLoaded() {
>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>> if (((AbstractPersistentCollection)
>>>>> delegate).wasInitialized()) {
>>>>> setIsLoaded(true);
>>>>> // log.debug("Persistentlist already initialized,
>>>>> probably eagerly loaded: " + getLogString());
>>>>> }
>>>>> }
>>>>> return super.isLoaded();
>>>>> }
>>>>>
>>>>> So let me describe full chain of events:
>>>>>
>>>>> There are THREE objects with lazy not loaded collections with
>>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>>> for collection it force hibernate to load this collection via
>>>>>
>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>
>>>>> and adds objects to resource.
>>>>>
>>>>> BUT during forcing of loading one delegate two other delegates were
>>>>> loaded too - they were marked as initialized. So two other
>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>
>>>>> public boolean isLoaded() {
>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>> if (((AbstractPersistentCollection)
>>>>> delegate).wasInitialized()) {
>>>>> setIsLoaded(true);
>>>>> // log.debug("Persistentlist already initialized,
>>>>> probably eagerly loaded: " + getLogString());
>>>>> }
>>>>> }
>>>>> return super.isLoaded();
>>>>> }
>>>>>
>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>
>>>>> This happens when fetch="subselect". Details of how
>>>>> fetch="subselect" works are in hibernate docs.
>>>>>
>>>>> My proposals:
>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>> check that objects are added - then isLoaded needs to be
>>>>> implemented like:
>>>>>
>>>>> public boolean isLoaded() {
>>>>> if (isLoaded){
>>>>> return true;
>>>>> }
>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>> if (((AbstractPersistentCollection)
>>>>> delegate).wasInitialized()) {
>>>>> setIsLoaded(true);
>>>>> // log.debug("Persistentlist already initialized,
>>>>> probably eagerly loaded: " + getLogString());
>>>>> }
>>>>> }
>>>>> return super.isLoaded();
>>>>> }
>>>>>
>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>
>>>>> Ilya
>>>>>
>>>>> Martin Taal wrote:
>>>>>> I do not fully understand what happens here. Can you describe the
>>>>>> case/example in which this occurs (automatically loading other
>>>>>> such collections)? The hibernate behavior as you describe it is
>>>>>> unfamiliar to me.
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>> Ilya Klyuchnikov wrote:
>>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>>> then all is OK until I have created association with
>>>>>>> fetch="subselect".
>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>> loaded they are not added to resource.
>>>>>>>
>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>> that are not loaded Hibernate can load all such collections. And
>>>>>>> fact of loading of other collections are not caught by Teneo.
>>>>>>>
>>>>>>> Is this a bug?
>>>>>>>
>>>>>>> Thanks
>>>>>>>
>>>>>>> Ilya
>>>>>>
>>>>>>
>>>
>>>
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600330 is a reply to message #65752] |
Wed, 27 December 2006 14:28 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Quotes from hibernate documentaion
( http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching):
Subselect fetching - a second SELECT is used to retrieve the associated
collections for ALL entities retrieved in a previous query or fetch.
Unless you explicitly disable lazy fetching by specifying lazy="false",
this second select will only be executed when you actually access the
association.
Ilya
Ilya Klyuchnikov wrote:
> The reason that fetch="subselect":
>
> With fetch="subselect" Hibernate loads ALL such collections on demand.
>
> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
> generates such query:
>
> Hibernate: select domain0_.`environment_id` as environm6_1_,
> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_, domain0_.e_version
> as e3_21_0_, domain0_.`name` as name4_21_0_, domain0_.`modified` as
> modified5_21_0_, domain0_.`environment_id` as environm6_21_0_ from
> `domain` domain0_ where domain0_.`environment_id` in (select
> deployment1_.`id` from environment_deploys deploysto0_ left outer join
> `environment` deployment1_ on deploysto0_.`from_id`=deployment1_.`id`
> where deploysto0_.`to_id`=?)
>
> Put attentions to where domain0_.`environment_id` in ...
>
> So this is a feature of Hibernate:
> If there are some not loaded collection corresponding to the same
> association (DeploymentEnvironment.domains in my example) having
> fetch="subselect" and client ask ONE of these collections to be loaded
> then Hibernate loads ALL collections. You can see this logic in
> AbstractCollectionPersister class.
>
> See
> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
> for details.
>
> Ilya
>
> Martin Taal wrote:
>> Yes for eagerly loaded lists I understand the issue. What I don't
>> understand is why the lazy loaded collections are loaded
>> (automatically). You say:
>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>> three
>> >>>> object with such lazy collections are already loaded
>>
>> What do you mean?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> In my example lazy="true".
>>>
>>> BTW, if there are collections with lazy="false" then during resource
>>> loading objects in such collections are not added to resource.
>>>
>>> Martin Taal wrote:
>>>> Hi Ilya,
>>>> Yes the solution is in the isLoaded method. If the underlying
>>>> hibernate collection is already loaded/initialized while
>>>> isLoaded=false then the children need to be added to the resource
>>>> (calling doLoad with some extra handling should work).
>>>>
>>>> Are the automatically loaded collections eager or lazy?
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>
>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>
>>>>> Ilya
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> Hi Martin
>>>>>>
>>>>>> I suppose that these details help you to understand problem:
>>>>>>
>>>>>> This is stack trace:
>>>>>>
>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>> AbstractPersistentCollection))
>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>>>> 366
>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>> line: 319
>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>> 315
>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> List, EntityMode) line: 268
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> Object, SessionImplementor) line: 249
>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 717
>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 224
>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>> SessionImplementor) line: 58
>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>> SessionImplementor) line: 565
>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>> line: 60
>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>> line: 1716
>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>>>> line: 86 PersistentBag.toArray() line: 257
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>> line: 339
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>> line: 380 As you see activity begins with:
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>
>>>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>>>
>>>>>> PROBLEM:
>>>>>>
>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>> three object with such lazy collections are already loaded - try
>>>>>> to investigate org.hibernate.engine.endLoadingCollections() method
>>>>>> - it has following code:
>>>>>>
>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>> resultSetCollections.size();
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections were found in result
>>>>>> set for role: " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> //now finish them
>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>>> resultSetCollections.get(i);
>>>>>> endLoadingCollection(lce, persister, em);
>>>>>> }
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections initialized for role:
>>>>>> " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>>> happened because my association has fetch="subselect".
>>>>>>
>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>
>>>>>> Why other were not added?
>>>>>>
>>>>>> Answer is simple:
>>>>>> Method doLoad() was not called for two other
>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>> is in this method. Why was notthis method called to two other
>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>
>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So let me describe full chain of events:
>>>>>>
>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>>>> for collection it force hibernate to load this collection via
>>>>>>
>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>
>>>>>> and adds objects to resource.
>>>>>>
>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>
>>>>>> This happens when fetch="subselect". Details of how
>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>
>>>>>> My proposals:
>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>> check that objects are added - then isLoaded needs to be
>>>>>> implemented like:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (isLoaded){
>>>>>> return true;
>>>>>> }
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>
>>>>>> Ilya
>>>>>>
>>>>>> Martin Taal wrote:
>>>>>>> I do not fully understand what happens here. Can you describe the
>>>>>>> case/example in which this occurs (automatically loading other
>>>>>>> such collections)? The hibernate behavior as you describe it is
>>>>>>> unfamiliar to me.
>>>>>>>
>>>>>>> gr. Martin
>>>>>>>
>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>>>> then all is OK until I have created association with
>>>>>>>> fetch="subselect".
>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>> loaded they are not added to resource.
>>>>>>>>
>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>>> that are not loaded Hibernate can load all such collections. And
>>>>>>>> fact of loading of other collections are not caught by Teneo.
>>>>>>>>
>>>>>>>> Is this a bug?
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>>> Ilya
>>>>>>>
>>>>>>>
>>>>
>>>>
>>
>>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600333 is a reply to message #65752] |
Wed, 27 December 2006 14:28 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Okay, clear, I will commit a fix for this this evening. Are you able to test the cvs version or make
the change locally?
gr. Martin
Ilya Klyuchnikov wrote:
> The reason that fetch="subselect":
>
> With fetch="subselect" Hibernate loads ALL such collections on demand.
>
> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
> generates such query:
>
> Hibernate: select domain0_.`environment_id` as environm6_1_,
> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_, domain0_.e_version
> as e3_21_0_, domain0_.`name` as name4_21_0_, domain0_.`modified` as
> modified5_21_0_, domain0_.`environment_id` as environm6_21_0_ from
> `domain` domain0_ where domain0_.`environment_id` in (select
> deployment1_.`id` from environment_deploys deploysto0_ left outer join
> `environment` deployment1_ on deploysto0_.`from_id`=deployment1_.`id`
> where deploysto0_.`to_id`=?)
>
> Put attentions to where domain0_.`environment_id` in ...
>
> So this is a feature of Hibernate:
> If there are some not loaded collection corresponding to the same
> association (DeploymentEnvironment.domains in my example) having
> fetch="subselect" and client ask ONE of these collections to be loaded
> then Hibernate loads ALL collections. You can see this logic in
> AbstractCollectionPersister class.
>
> See
> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
> for details.
>
> Ilya
>
> Martin Taal wrote:
>> Yes for eagerly loaded lists I understand the issue. What I don't
>> understand is why the lazy loaded collections are loaded
>> (automatically). You say:
>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>> three
>> >>>> object with such lazy collections are already loaded
>>
>> What do you mean?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> In my example lazy="true".
>>>
>>> BTW, if there are collections with lazy="false" then during resource
>>> loading objects in such collections are not added to resource.
>>>
>>> Martin Taal wrote:
>>>> Hi Ilya,
>>>> Yes the solution is in the isLoaded method. If the underlying
>>>> hibernate collection is already loaded/initialized while
>>>> isLoaded=false then the children need to be added to the resource
>>>> (calling doLoad with some extra handling should work).
>>>>
>>>> Are the automatically loaded collections eager or lazy?
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>
>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>
>>>>> Ilya
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> Hi Martin
>>>>>>
>>>>>> I suppose that these details help you to understand problem:
>>>>>>
>>>>>> This is stack trace:
>>>>>>
>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>> AbstractPersistentCollection))
>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized() line:
>>>>>> 366
>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>> line: 319
>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>> 315
>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> List, EntityMode) line: 268
>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>> Object, SessionImplementor) line: 249
>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 717
>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>> QueryParameters, boolean) line: 224
>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>> SessionImplementor) line: 58
>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>> SessionImplementor) line: 565
>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>> line: 60
>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>> line: 1716
>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>> line: 344 PersistentBag(AbstractPersistentCollection).read()
>>>>>> line: 86 PersistentBag.toArray() line: 257
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>> HibernatePersistableEList(PersistableEList).load() line: 187
>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>> line: 339
>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>> line: 380 As you see activity begins with:
>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>
>>>>>> and PersistentBag is marked as initialized BUT: request was passed
>>>>>> to EXACTLY ONE HibernatePersistableEList - so after PersistentBag
>>>>>> corresponding to THIS HibernatePersistableEList was loaded all
>>>>>> objects contained in PersistentBag are added to resource - it's OK.
>>>>>>
>>>>>> PROBLEM:
>>>>>>
>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>> three object with such lazy collections are already loaded - try
>>>>>> to investigate org.hibernate.engine.endLoadingCollections() method
>>>>>> - it has following code:
>>>>>>
>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>> resultSetCollections.size();
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections were found in result
>>>>>> set for role: " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> //now finish them
>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>>> resultSetCollections.get(i);
>>>>>> endLoadingCollection(lce, persister, em);
>>>>>> }
>>>>>>
>>>>>> if ( log.isDebugEnabled() ) {
>>>>>> log.debug( count + " collections initialized for role:
>>>>>> " + persister.getRole() );
>>>>>> }
>>>>>>
>>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>>> happened because my association has fetch="subselect".
>>>>>>
>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>
>>>>>> Why other were not added?
>>>>>>
>>>>>> Answer is simple:
>>>>>> Method doLoad() was not called for two other
>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>> is in this method. Why was notthis method called to two other
>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>
>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So let me describe full chain of events:
>>>>>>
>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>> fetch="subselect". When one of HibernatePersistableELists is asked
>>>>>> for collection it force hibernate to load this collection via
>>>>>>
>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>
>>>>>> and adds objects to resource.
>>>>>>
>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>
>>>>>> This happens when fetch="subselect". Details of how
>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>
>>>>>> My proposals:
>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>> check that objects are added - then isLoaded needs to be
>>>>>> implemented like:
>>>>>>
>>>>>> public boolean isLoaded() {
>>>>>> if (isLoaded){
>>>>>> return true;
>>>>>> }
>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>> if (((AbstractPersistentCollection)
>>>>>> delegate).wasInitialized()) {
>>>>>> setIsLoaded(true);
>>>>>> // log.debug("Persistentlist already initialized,
>>>>>> probably eagerly loaded: " + getLogString());
>>>>>> }
>>>>>> }
>>>>>> return super.isLoaded();
>>>>>> }
>>>>>>
>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>
>>>>>> Ilya
>>>>>>
>>>>>> Martin Taal wrote:
>>>>>>> I do not fully understand what happens here. Can you describe the
>>>>>>> case/example in which this occurs (automatically loading other
>>>>>>> such collections)? The hibernate behavior as you describe it is
>>>>>>> unfamiliar to me.
>>>>>>>
>>>>>>> gr. Martin
>>>>>>>
>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>> When I use HibernateResource with loading strategy addToContents
>>>>>>>> then all is OK until I have created association with
>>>>>>>> fetch="subselect".
>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>> loaded they are not added to resource.
>>>>>>>>
>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>>> that are not loaded Hibernate can load all such collections. And
>>>>>>>> fact of loading of other collections are not caught by Teneo.
>>>>>>>>
>>>>>>>> Is this a bug?
>>>>>>>>
>>>>>>>> Thanks
>>>>>>>>
>>>>>>>> Ilya
>>>>>>>
>>>>>>>
>>>>
>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600343 is a reply to message #65798] |
Wed, 27 December 2006 15:24 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Ilya Klyuchnikov![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=ilya.klyuchnikov%40gmail.com) Messages: 74 Registered: July 2009 |
Member |
|
|
Sorry Martin,
It is time consuming for me to build and test Teneo cvs version.
I think that I will be able to test your changes on Friday evening only.
Ilya
Martin Taal wrote:
> Okay, clear, I will commit a fix for this this evening. Are you able to
> test the cvs version or make the change locally?
>
> gr. Martin
>
> Ilya Klyuchnikov wrote:
>> The reason that fetch="subselect":
>>
>> With fetch="subselect" Hibernate loads ALL such collections on demand.
>>
>> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
>> generates such query:
>>
>> Hibernate: select domain0_.`environment_id` as environm6_1_,
>> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_,
>> domain0_.e_version as e3_21_0_, domain0_.`name` as name4_21_0_,
>> domain0_.`modified` as modified5_21_0_, domain0_.`environment_id` as
>> environm6_21_0_ from `domain` domain0_ where domain0_.`environment_id`
>> in (select deployment1_.`id` from environment_deploys deploysto0_ left
>> outer join `environment` deployment1_ on
>> deploysto0_.`from_id`=deployment1_.`id` where deploysto0_.`to_id`=?)
>>
>> Put attentions to where domain0_.`environment_id` in ...
>>
>> So this is a feature of Hibernate:
>> If there are some not loaded collection corresponding to the same
>> association (DeploymentEnvironment.domains in my example) having
>> fetch="subselect" and client ask ONE of these collections to be loaded
>> then Hibernate loads ALL collections. You can see this logic in
>> AbstractCollectionPersister class.
>>
>> See
>> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
>> for details.
>>
>> Ilya
>>
>> Martin Taal wrote:
>>> Yes for eagerly loaded lists I understand the issue. What I don't
>>> understand is why the lazy loaded collections are loaded
>>> (automatically). You say:
>>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>>> three
>>> >>>> object with such lazy collections are already loaded
>>>
>>> What do you mean?
>>>
>>> gr. Martin
>>>
>>> Ilya Klyuchnikov wrote:
>>>> In my example lazy="true".
>>>>
>>>> BTW, if there are collections with lazy="false" then during resource
>>>> loading objects in such collections are not added to resource.
>>>>
>>>> Martin Taal wrote:
>>>>> Hi Ilya,
>>>>> Yes the solution is in the isLoaded method. If the underlying
>>>>> hibernate collection is already loaded/initialized while
>>>>> isLoaded=false then the children need to be added to the resource
>>>>> (calling doLoad with some extra handling should work).
>>>>>
>>>>> Are the automatically loaded collections eager or lazy?
>>>>>
>>>>> gr. Martin
>>>>>
>>>>> Ilya Klyuchnikov wrote:
>>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>>
>>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>>
>>>>>> Ilya
>>>>>>
>>>>>> Ilya Klyuchnikov wrote:
>>>>>>> Hi Martin
>>>>>>>
>>>>>>> I suppose that these details help you to understand problem:
>>>>>>>
>>>>>>> This is stack trace:
>>>>>>>
>>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>>> AbstractPersistentCollection))
>>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized()
>>>>>>> line: 366
>>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>>> line: 319
>>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>>> 315
>>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>> List, EntityMode) line: 268
>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>> Object, SessionImplementor) line: 249
>>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>>> QueryParameters, boolean) line: 717
>>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>>> QueryParameters, boolean) line: 224
>>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>>> SessionImplementor) line: 58
>>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>>> SessionImplementor) line: 565
>>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>>> line: 60
>>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>>> line: 1716
>>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>>> line: 344
>>>>>>> PersistentBag(AbstractPersistentCollection).read() line: 86
>>>>>>> PersistentBag.toArray() line: 257
>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>> HibernatePersistableEList(PersistableEList).load() line:
>>>>>>> 187
>>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>>> 395 HibernatePersistableEList(DelegatingEList).size() line:
>>>>>>> 214 DelegatingEList$EIterator.hasNext() line: 1000
>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>>> line: 339
>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>>> line: 380 As you see activity begins with:
>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>>
>>>>>>> and PersistentBag is marked as initialized BUT: request was
>>>>>>> passed to EXACTLY ONE HibernatePersistableEList - so after
>>>>>>> PersistentBag corresponding to THIS HibernatePersistableEList was
>>>>>>> loaded all objects contained in PersistentBag are added to
>>>>>>> resource - it's OK.
>>>>>>>
>>>>>>> PROBLEM:
>>>>>>>
>>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>>> three object with such lazy collections are already loaded - try
>>>>>>> to investigate org.hibernate.engine.endLoadingCollections()
>>>>>>> method - it has following code:
>>>>>>>
>>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>>> resultSetCollections.size();
>>>>>>>
>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>> log.debug( count + " collections were found in result
>>>>>>> set for role: " + persister.getRole() );
>>>>>>> }
>>>>>>>
>>>>>>> //now finish them
>>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>>> LoadingCollectionEntry lce = (LoadingCollectionEntry)
>>>>>>> resultSetCollections.get(i);
>>>>>>> endLoadingCollection(lce, persister, em);
>>>>>>> }
>>>>>>>
>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>> log.debug( count + " collections initialized for
>>>>>>> role: " + persister.getRole() );
>>>>>>> }
>>>>>>>
>>>>>>> In my example count = 3. So THREE PersistentBags were loaded - it
>>>>>>> happened because my association has fetch="subselect".
>>>>>>>
>>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>>
>>>>>>> Why other were not added?
>>>>>>>
>>>>>>> Answer is simple:
>>>>>>> Method doLoad() was not called for two other
>>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>>> is in this method. Why was notthis method called to two other
>>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>>
>>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>>
>>>>>>> public boolean isLoaded() {
>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>> if (((AbstractPersistentCollection)
>>>>>>> delegate).wasInitialized()) {
>>>>>>> setIsLoaded(true);
>>>>>>> // log.debug("Persistentlist already initialized,
>>>>>>> probably eagerly loaded: " + getLogString());
>>>>>>> }
>>>>>>> }
>>>>>>> return super.isLoaded();
>>>>>>> }
>>>>>>>
>>>>>>> So let me describe full chain of events:
>>>>>>>
>>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>>> fetch="subselect". When one of HibernatePersistableELists is
>>>>>>> asked for collection it force hibernate to load this collection via
>>>>>>>
>>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>>
>>>>>>> and adds objects to resource.
>>>>>>>
>>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>>
>>>>>>> public boolean isLoaded() {
>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>> if (((AbstractPersistentCollection)
>>>>>>> delegate).wasInitialized()) {
>>>>>>> setIsLoaded(true);
>>>>>>> // log.debug("Persistentlist already initialized,
>>>>>>> probably eagerly loaded: " + getLogString());
>>>>>>> }
>>>>>>> }
>>>>>>> return super.isLoaded();
>>>>>>> }
>>>>>>>
>>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>>
>>>>>>> This happens when fetch="subselect". Details of how
>>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>>
>>>>>>> My proposals:
>>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>>> check that objects are added - then isLoaded needs to be
>>>>>>> implemented like:
>>>>>>>
>>>>>>> public boolean isLoaded() {
>>>>>>> if (isLoaded){
>>>>>>> return true;
>>>>>>> }
>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>> if (((AbstractPersistentCollection)
>>>>>>> delegate).wasInitialized()) {
>>>>>>> setIsLoaded(true);
>>>>>>> // log.debug("Persistentlist already initialized,
>>>>>>> probably eagerly loaded: " + getLogString());
>>>>>>> }
>>>>>>> }
>>>>>>> return super.isLoaded();
>>>>>>> }
>>>>>>>
>>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>>
>>>>>>> Ilya
>>>>>>>
>>>>>>> Martin Taal wrote:
>>>>>>>> I do not fully understand what happens here. Can you describe
>>>>>>>> the case/example in which this occurs (automatically loading
>>>>>>>> other such collections)? The hibernate behavior as you describe
>>>>>>>> it is unfamiliar to me.
>>>>>>>>
>>>>>>>> gr. Martin
>>>>>>>>
>>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>>> When I use HibernateResource with loading strategy
>>>>>>>>> addToContents then all is OK until I have created association
>>>>>>>>> with fetch="subselect".
>>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>>> loaded they are not added to resource.
>>>>>>>>>
>>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>>> ONE such collection BUT if there are any other such collections
>>>>>>>>> that are not loaded Hibernate can load all such collections.
>>>>>>>>> And fact of loading of other collections are not caught by Teneo.
>>>>>>>>>
>>>>>>>>> Is this a bug?
>>>>>>>>>
>>>>>>>>> Thanks
>>>>>>>>>
>>>>>>>>> Ilya
>>>>>>>>
>>>>>>>>
>>>>>
>>>>>
>>>
>>>
>
>
|
|
|
Re: Teneo: Objects are not added to resource.contents if fetch="subselect" for collection [message #600400 is a reply to message #65822] |
Fri, 29 December 2006 08:19 ![Go to previous message Go to previous message](theme/Solstice/images/up.png) |
Martin Taal![Friend of Eclipse Friend](/donate/web-api/friends_decorator.php?email=mtaal%40springsite.com) Messages: 5468 Registered: July 2009 |
Senior Member |
|
|
Hi Ilya,
You can try the latest build here, that's easier then using the cvs version:
http://emft.eclipse.org/emft/downloads/index.php?project=ten eo&showAll=0&showMax=10&sortBy=date
gr. Martin
Ilya Klyuchnikov wrote:
> Sorry Martin,
>
> It is time consuming for me to build and test Teneo cvs version.
>
> I think that I will be able to test your changes on Friday evening only.
>
> Ilya
>
> Martin Taal wrote:
>> Okay, clear, I will commit a fix for this this evening. Are you able
>> to test the cvs version or make the change locally?
>>
>> gr. Martin
>>
>> Ilya Klyuchnikov wrote:
>>> The reason that fetch="subselect":
>>>
>>> With fetch="subselect" Hibernate loads ALL such collections on demand.
>>>
>>> In my example when I ask DeploymentEnvironment.getDomains() Hibernate
>>> generates such query:
>>>
>>> Hibernate: select domain0_.`environment_id` as environm6_1_,
>>> domain0_.`id` as id1_1_, domain0_.`id` as id1_21_0_,
>>> domain0_.e_version as e3_21_0_, domain0_.`name` as name4_21_0_,
>>> domain0_.`modified` as modified5_21_0_, domain0_.`environment_id` as
>>> environm6_21_0_ from `domain` domain0_ where
>>> domain0_.`environment_id` in (select deployment1_.`id` from
>>> environment_deploys deploysto0_ left outer join `environment`
>>> deployment1_ on deploysto0_.`from_id`=deployment1_.`id` where
>>> deploysto0_.`to_id`=?)
>>>
>>> Put attentions to where domain0_.`environment_id` in ...
>>>
>>> So this is a feature of Hibernate:
>>> If there are some not loaded collection corresponding to the same
>>> association (DeploymentEnvironment.domains in my example) having
>>> fetch="subselect" and client ask ONE of these collections to be
>>> loaded then Hibernate loads ALL collections. You can see this logic
>>> in AbstractCollectionPersister class.
>>>
>>> See
>>> http://www.hibernate.org/hib_docs/v3/reference/en/html/perfo rmance.html#performance-fetching
>>> for details.
>>>
>>> Ilya
>>>
>>> Martin Taal wrote:
>>>> Yes for eagerly loaded lists I understand the issue. What I don't
>>>> understand is why the lazy loaded collections are loaded
>>>> (automatically). You say:
>>>> >>>> Actually in my example THREE PersistentBag were loaded - cause
>>>> three
>>>> >>>> object with such lazy collections are already loaded
>>>>
>>>> What do you mean?
>>>>
>>>> gr. Martin
>>>>
>>>> Ilya Klyuchnikov wrote:
>>>>> In my example lazy="true".
>>>>>
>>>>> BTW, if there are collections with lazy="false" then during
>>>>> resource loading objects in such collections are not added to
>>>>> resource.
>>>>>
>>>>> Martin Taal wrote:
>>>>>> Hi Ilya,
>>>>>> Yes the solution is in the isLoaded method. If the underlying
>>>>>> hibernate collection is already loaded/initialized while
>>>>>> isLoaded=false then the children need to be added to the resource
>>>>>> (calling doLoad with some extra handling should work).
>>>>>>
>>>>>> Are the automatically loaded collections eager or lazy?
>>>>>>
>>>>>> gr. Martin
>>>>>>
>>>>>> Ilya Klyuchnikov wrote:
>>>>>>> Sorry - I misprinted method name where ALL INTERESTING happens:
>>>>>>>
>>>>>>> org.hibernate.engine.CollectionLoadContext.endLoadingCollect ions()
>>>>>>> instead of org.hibernate.engine.endLoadingCollections()
>>>>>>>
>>>>>>> Ilya
>>>>>>>
>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>> Hi Martin
>>>>>>>>
>>>>>>>> I suppose that these details help you to understand problem:
>>>>>>>>
>>>>>>>> This is stack trace:
>>>>>>>>
>>>>>>>> Thread [main] (Suspended (breakpoint at line 366 in
>>>>>>>> AbstractPersistentCollection))
>>>>>>>> PersistentBag(AbstractPersistentCollection).setInitialized()
>>>>>>>> line: 366
>>>>>>>> PersistentBag(AbstractPersistentCollection).afterInitialize( )
>>>>>>>> line: 319
>>>>>>>> PersistentBag(AbstractPersistentCollection).endRead() line:
>>>>>>>> 315
>>>>>>>> CollectionLoadContext.endLoadingCollection(CollectionLoadCon text$LoadingCollectionEntry,
>>>>>>>> CollectionPersister, EntityMode) line: 183
>>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>>> List, EntityMode) line: 268
>>>>>>>> CollectionLoadContext.endLoadingCollections(CollectionPersis ter,
>>>>>>>> Object, SessionImplementor) line: 249
>>>>>>>> SubselectOneToManyLoader(Loader).endCollectionLoad(Object,
>>>>>>>> SessionImplementor, CollectionPersister) line: 866
>>>>>>>> SubselectOneToManyLoader(Loader).initializeEntitiesAndCollec tions(List,
>>>>>>>> Object, SessionImplementor, boolean) line: 853
>>>>>>>> SubselectOneToManyLoader(Loader).doQuery(SessionImplementor,
>>>>>>>> QueryParameters, boolean) line: 717
>>>>>>>> SubselectOneToManyLoader(Loader).doQueryAndInitializeNonLazy Collections(SessionImplementor,
>>>>>>>> QueryParameters, boolean) line: 224
>>>>>>>> SubselectOneToManyLoader(Loader).loadCollectionSubselect(Ses sionImplementor,
>>>>>>>> Serializable[], Object[], Type[], Map, Type) line: 1990
>>>>>>>> SubselectOneToManyLoader.initialize(Serializable,
>>>>>>>> SessionImplementor) line: 58
>>>>>>>> OneToManyPersister(AbstractCollectionPersister).initialize(S erializable,
>>>>>>>> SessionImplementor) line: 565
>>>>>>>> DefaultInitializeCollectionEventListener.onInitializeCollect ion(InitializeCollectionEvent)
>>>>>>>> line: 60
>>>>>>>> SessionImpl.initializeCollection(PersistentCollection, boolean)
>>>>>>>> line: 1716
>>>>>>>> PersistentBag(AbstractPersistentCollection).initialize(boole an)
>>>>>>>> line: 344
>>>>>>>> PersistentBag(AbstractPersistentCollection).read() line:
>>>>>>>> 86 PersistentBag.toArray() line: 257
>>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>>> HibernatePersistableEList(PersistableEList).load() line:
>>>>>>>> 187
>>>>>>>> HibernatePersistableEList(PersistableEList).delegateSize() line:
>>>>>>>> 395 HibernatePersistableEList(DelegatingEList).size()
>>>>>>>> line: 214 DelegatingEList$EIterator.hasNext() line:
>>>>>>>> 1000
>>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).getCh ildren(Object)
>>>>>>>> line: 339
>>>>>>>> DeploymentEnvironmentItemProvider(ItemProviderAdapter).hasCh ildren(Object)
>>>>>>>> line: 380 As you see activity begins with:
>>>>>>>> HibernatePersistableEList.doLoad() line: 106
>>>>>>>>
>>>>>>>> and PersistentBag is marked as initialized BUT: request was
>>>>>>>> passed to EXACTLY ONE HibernatePersistableEList - so after
>>>>>>>> PersistentBag corresponding to THIS HibernatePersistableEList
>>>>>>>> was loaded all objects contained in PersistentBag are added to
>>>>>>>> resource - it's OK.
>>>>>>>>
>>>>>>>> PROBLEM:
>>>>>>>>
>>>>>>>> Actually in my example THREE PersistentBag were loaded - cause
>>>>>>>> three object with such lazy collections are already loaded - try
>>>>>>>> to investigate org.hibernate.engine.endLoadingCollections()
>>>>>>>> method - it has following code:
>>>>>>>>
>>>>>>>> final int count = (resultSetCollections == null) ? 0 :
>>>>>>>> resultSetCollections.size();
>>>>>>>>
>>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>>> log.debug( count + " collections were found in
>>>>>>>> result set for role: " + persister.getRole() );
>>>>>>>> }
>>>>>>>>
>>>>>>>> //now finish them
>>>>>>>> for ( int i = 0; i < count; i++ ) {
>>>>>>>> LoadingCollectionEntry lce =
>>>>>>>> (LoadingCollectionEntry) resultSetCollections.get(i);
>>>>>>>> endLoadingCollection(lce, persister, em);
>>>>>>>> }
>>>>>>>>
>>>>>>>> if ( log.isDebugEnabled() ) {
>>>>>>>> log.debug( count + " collections initialized for
>>>>>>>> role: " + persister.getRole() );
>>>>>>>> }
>>>>>>>>
>>>>>>>> In my example count = 3. So THREE PersistentBags were loaded -
>>>>>>>> it happened because my association has fetch="subselect".
>>>>>>>>
>>>>>>>> So THREE PersistentBags were were marked as initialized but ONLY
>>>>>>>> object from ONE OF THEM were added to contents of resource.
>>>>>>>>
>>>>>>>> Why other were not added?
>>>>>>>>
>>>>>>>> Answer is simple:
>>>>>>>> Method doLoad() was not called for two other
>>>>>>>> HibernatePersistableEList. Adding objects to resource.contents()
>>>>>>>> is in this method. Why was notthis method called to two other
>>>>>>>> list? Cause it is called only if isLoaded() returns false.
>>>>>>>>
>>>>>>>> BUT HOW is this method implemented for HibernatePersistableEList?
>>>>>>>>
>>>>>>>> public boolean isLoaded() {
>>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>>> if (((AbstractPersistentCollection)
>>>>>>>> delegate).wasInitialized()) {
>>>>>>>> setIsLoaded(true);
>>>>>>>> // log.debug("Persistentlist already
>>>>>>>> initialized, probably eagerly loaded: " + getLogString());
>>>>>>>> }
>>>>>>>> }
>>>>>>>> return super.isLoaded();
>>>>>>>> }
>>>>>>>>
>>>>>>>> So let me describe full chain of events:
>>>>>>>>
>>>>>>>> There are THREE objects with lazy not loaded collections with
>>>>>>>> fetch="subselect". When one of HibernatePersistableELists is
>>>>>>>> asked for collection it force hibernate to load this collection via
>>>>>>>>
>>>>>>>> Object[] objs = delegate.toArray(); // this forces the load
>>>>>>>>
>>>>>>>> and adds objects to resource.
>>>>>>>>
>>>>>>>> BUT during forcing of loading one delegate two other delegates
>>>>>>>> were loaded too - they were marked as initialized. So two other
>>>>>>>> HibernatePersistableELists will return isLoaded() = true because:
>>>>>>>>
>>>>>>>> public boolean isLoaded() {
>>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>>> if (((AbstractPersistentCollection)
>>>>>>>> delegate).wasInitialized()) {
>>>>>>>> setIsLoaded(true);
>>>>>>>> // log.debug("Persistentlist already
>>>>>>>> initialized, probably eagerly loaded: " + getLogString());
>>>>>>>> }
>>>>>>>> }
>>>>>>>> return super.isLoaded();
>>>>>>>> }
>>>>>>>>
>>>>>>>> So Teneo looses the moment when delegate is really initialized.
>>>>>>>>
>>>>>>>> This happens when fetch="subselect". Details of how
>>>>>>>> fetch="subselect" works are in hibernate docs.
>>>>>>>>
>>>>>>>> My proposals:
>>>>>>>> You can override setIsLoaded() in HibernatePersistableELists and
>>>>>>>> check that objects are added - then isLoaded needs to be
>>>>>>>> implemented like:
>>>>>>>>
>>>>>>>> public boolean isLoaded() {
>>>>>>>> if (isLoaded){
>>>>>>>> return true;
>>>>>>>> }
>>>>>>>> if (delegate instanceof AbstractPersistentCollection) {
>>>>>>>> if (((AbstractPersistentCollection)
>>>>>>>> delegate).wasInitialized()) {
>>>>>>>> setIsLoaded(true);
>>>>>>>> // log.debug("Persistentlist already
>>>>>>>> initialized, probably eagerly loaded: " + getLogString());
>>>>>>>> }
>>>>>>>> }
>>>>>>>> return super.isLoaded();
>>>>>>>> }
>>>>>>>>
>>>>>>>> Feel free to ask me for more details if my answer is not enough.
>>>>>>>>
>>>>>>>> Ilya
>>>>>>>>
>>>>>>>> Martin Taal wrote:
>>>>>>>>> I do not fully understand what happens here. Can you describe
>>>>>>>>> the case/example in which this occurs (automatically loading
>>>>>>>>> other such collections)? The hibernate behavior as you describe
>>>>>>>>> it is unfamiliar to me.
>>>>>>>>>
>>>>>>>>> gr. Martin
>>>>>>>>>
>>>>>>>>> Ilya Klyuchnikov wrote:
>>>>>>>>>> When I use HibernateResource with loading strategy
>>>>>>>>>> addToContents then all is OK until I have created association
>>>>>>>>>> with fetch="subselect".
>>>>>>>>>> Sometimes objects that are inside these lazy collections are
>>>>>>>>>> loaded they are not added to resource.
>>>>>>>>>>
>>>>>>>>>> As far as I understand it happens when I ask some objects from
>>>>>>>>>> ONE such collection BUT if there are any other such
>>>>>>>>>> collections that are not loaded Hibernate can load all such
>>>>>>>>>> collections. And fact of loading of other collections are not
>>>>>>>>>> caught by Teneo.
>>>>>>>>>>
>>>>>>>>>> Is this a bug?
>>>>>>>>>>
>>>>>>>>>> Thanks
>>>>>>>>>>
>>>>>>>>>> Ilya
>>>>>>>>>
>>>>>>>>>
>>>>>>
>>>>>>
>>>>
>>>>
>>
>>
--
With Regards, Martin Taal
Springsite/Elver.org
Office: Hardwareweg 4, 3821 BV Amersfoort
Postal: Nassaulaan 7, 3941 EC Doorn
The Netherlands
Tel: +31 (0)84 420 2397
Fax: +31 (0)84 225 9307
Mail: mtaal@springsite.com - mtaal@elver.org
Web: www.springsite.com - www.elver.org
|
|
|
Goto Forum:
Current Time: Sun Sep 01 11:06:15 GMT 2024
Powered by FUDForum. Page generated in 0.06185 seconds
|