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.
