Re: Standalone prefetch without main query?
John Pollard <[email protected]>
| Newsgroups | gmane.comp.web.webobjects.eof |
|---|---|
| Message-ID | <[email protected]> |
Jonathan,
Thank you for your replies.
Your solution 1 is something I had tried but it doesn't prevent the
additional queries. Fetching the objects into the ec with a fetch spec does
prevent to-one faults causing a db query as the fault contains the object
id and finds the actual object in memory. But to-many faults STILL result
in a db query each (not one query per object, but one query for the each
to-many relationship). This is understandable because a to-many fault
doesn't contain the object ids of all the many objects in the relationship
so it has to go and get them even if each individual object in that to-many
relationship happens to be in memory.
Your solution 2 is very close to what I need, I now see that petite_abeille
posted some similar info a while ago. The problem is that it can't cope
with second level relationships. When using
setPrefetchingRelationshipKeyPaths() on a fetch spec it is possible and in
my case necessary to set more than one keypath and to include a second
level relationship, for example "stockItems" and
"stockItems.stockByLocations". The batchFetchRelationship() method fails if
given a keypath deeper than 1 rather than the simple relationship name. The
fetch spec prefetching code is doing something clever in interpreting the
keypath into a query based on the main objects and intermediate objects in
the keypath. I need batchFetchRelationship() to do a similar thing.
Another problem with solution 2 is that the EODatabaseContext class which
is in the EOAccess layer is not available on the client side of a JC
application where I would also like to use this trick.
However, it is still useful where one needs to preload a first level
to-many relationship. Here is an example method that implements your
suggestion for that:
// Given an array of base objects and the name of a (to-many) relationship
on those objects,
// load up the contents of all of those relationships. This is slightly
different to prefetching because the
// base objects themselves don't have to be queried at all - only the
prefetch part is carried out
public static void preloadRelationship(NSArray baseObjects, String
relationshipName)
{
if(baseObjects != null && baseObjects.count() != 0)
{
EOEnterpriseObject tokenBaseEO = (EOEnterpriseObject)
baseObjects.objectAtIndex(0);
EOEditingContext ec = tokenBaseEO.editingContext();
EOEntity entityClass =
EOModelGroup.defaultGroup().entityNamed(tokenBaseEO.entityName());
EODatabaseContext databaseContext =
EODatabaseContext.registeredDatabaseContextForModel(entityClass.model(), ec);
EORelationship relationship =
entityClass.relationshipNamed(relationshipName);
databaseContext.batchFetchRelationship(relationship, baseObjects, ec);
}
}
Thanks again
John
At 10:27 30/10/2002 -0600, Jonathan Rochkind wrote:
>1. Remember that EOEditingContexts do uniquing, meaning that if there's a
>'fault' for a particular StockItem, and then you fetch that StockItem on
>your own with a fetch spec, that 'fault' is now a real object and
>accessing it won't be a trip to the db. That is, you don't need to run
>the query against the StockGroup to 'populate' it's relationship---you
>just need to fetch the StockItems in question.
>
>I forgot this myself for a while and gave myself a lot of unneccesary work.
>
>So, one option would be to construct a fetch spec to fetch all those
>StockItems you know you'll need. Some qualifier like "stockGroup = %@ OR
>stockGroup = %@ OR stockGroup =%@" etc. Note that you can construct an
>EOQualifier of the form "relationship = EOEnterpriseObject", you don't
>actually need to deal with the primary/foreign keys.
>
>2. Batch faulting, as opposed to fetching, may also be of use to you
>here. See:
>http://developer.apple.com/techpubs/webobjects/WebObjects_5/Topics/ProgrammingTopics.8.html
>
>Actually, that documentation is kind of sketchy (and not updated for WO5),
>now that I look at it. 'Batch faulting' is kind of a misnomer for what I'm
>reccomending, which is specifically the EODatabaseContext method
>
>batchFetchRelationship(EORelationship relationship, NSArray objects,
>EOEditingContext editingContext)
>
>It does pretty much exactly what you want, although you inconveniently
>need to look up the actual EORelationship object, not just give it the
>name of the relationship. You could write a utility method that takes a
>String relationship name instead, and looks up the EORelationship (by
>taking a typical object from the NSArray and looking up it's EOEntity).
>
>
>At 11:14 AM 10/30/2002 +0000, John Pollard wrote:
>>An eof prefetch brain teaser,
>>
>>I have an object StockGroup that has a relationship stockItems(). I have
>>a number of StockGroup objects already in my editing context. I know I am
>>going to access all of the stockItems() arrays so I don't want a query
>>triggered for each one.
>>
>>The solution I have come up with is to write a fetch spec to fetch
>>StockGroups based on their primary keys and to prefetch the stockItems
>>relationship.
>>
>>That is not bad because it results in just two queries (the StockGroup
>>query and the StockItem prefetch query). However, in an ideal world I
>>only need the second (prefetch) query to execute because I already have
>>the StockGroups in memory.
>>
>>I am only running the query against the StockGroup entity because it is
>>the only way I know to populate the stockItems() of a number of
>>StockGroups in one go. Is there another way? Some way I can just run the
>>prefetch bit of the query which is the bit I need?
>>
>>Thanks
>>John
>>
>>_______________________________________________
>>EOF mailing list
>>[email protected]
>>http://www.omnigroup.com/mailman/listinfo/eof
>
>_______________________________________________
>EOF mailing list
>[email protected]
>http://www.omnigroup.com/mailman/listinfo/eof