On Fri, Mar 12, 2010 at 4:26 PM, John Patterson <[email protected]> wrote:
>
> I really don't see what you think is magical about an initialized instance.
>  I repeat: by default this feature is off and all data is loaded as
> expected.  No magic. No Proxies.  Just simple plain POJOs.  Definitely some
> FUD in the air tonight.

It's hardly FUD to point out that every extra query counts.  In GAE,
you can measure the price (in $) of every single request.  In the
applications I have developed, it *matters* that you don't do multiple
queries to fetch excess data.

For nontrivial applications, fetching a large object graph every time
you load an object just doesn't work.  This is why Hibernate added
proxies.  I'm glad you're sufficiently aware of this problem that
you're building in limits to activation, but I think you're nuts if
you think that these facilities will rarely be used.

>> It really is instructive to follow how this feature (in the form of
>> proxies) evolved in Hibernate (and JPA).
>
> Proxies are a completely different beast.  If bytecode manipulation were
> used there are suddenly serialization problems to worry about.  That is why
> Twig uses pure plain POJOs with NO magic.  As simple as possible.

Proxies serve the exact same purpose as your uninitialized entities.
They allow the fetch process to halt, because in nontrivial
applications you cannot afford to load large object graphs every time
you fetch a single entity.  As a solution, proxies have advantages and
disadvantages - just like your uninitialized entities have advantages
and disadvantages.

FWIW, I myself prefer the uninitialized entity solution over proxies,
despite the - quite significant - danger.  Just remember that if
everyone was using Twig instead of Hibernate, all those
LazyInitializationExceptions - 64,500 google hits for "hibernate
lazyinitializationexception" - would in fact be method calls silently
returning invalid data.

Before you say "but the default is to fetch everything!" please
realize that Hibernate has the option to "fetch everything" as well,
and nobody uses it for the same reason they won't use it in Twig - you
normally can't get away with loading large object graphs when you
fetch a single entity.

This isn't FUD, it's being realistic based on the real-world
experiences of people using a popular framework with similar features.
 After you explained the concept of uninitialized entities (the brief
blurb in your docs really isn't enough), I actually rather like your
solution!  I might even implement something similar in Objectify.  But
I really think you need to document the hell out of the issues
surrounding them.  It is very very easy to corrupt data.

Sadly, this is where bytecode manipulation really would come in handy
- you can intercept data access on an uninitialized entity and throw
an exception.  It's too bad java dynamic proxies can't wrap concrete
classes.

> This is controllable in *very* fine detail by Activation settings.  Any
> class can have a default activation depth, any field can have an activation
> depth and the datastore as a whole can set the depth for any individual
> operation.  This gives *complete* control over what is loaded and when.

I wouldn't call it complete control.  It doesn't very gracefully
handle entities with multiple relationships - some queries you will
want to fetch some parts and not others.  However, the point is moot,
since you can (and IMNSHO probably should) always disable automatic
activation and refresh the graph manually.

Here's a bit of free advice:  You need a batch refresh() operation.

> Your comparison to Hibernate is not really accurate.  You see the the
> difference is that Hibernate was built to optimise working with RDBMS
> systems that can do JOINs and therefore fetch data in bulk.  The datastore
> cannot do JOINs and probably never will so options like FETCH are just not
> required.

Actually, this makes the situation even *more* dire in GAE than it is
in Hibernate.  In Hibernate, extra fetching means extra JOINs in the
query.  In GAE, extra fetching means doing whole additional roundtrips
to the datastore - essentially manual joins.  The fetch/activation
limits are very important.

Jeff

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to