Thanks John and Jeff for sharing the knowledge. I've just quickly scanned your project home, and I have a novice question that needs your help: Is twig or Objectify direct replacement to JDO / JPA on GAE? I just need to use your framework alone, or should use in combination with JDO / JPA support?
What is about the approach implementing "general" JDO / JPA fit to Datastore? Is there a chance Google provide a specific implementation to their Datastore? Maybe someone from Google can advise on this? Thanks, -Chau On Tue, Jan 26, 2010 at 2:52 PM, John Patterson <[email protected]>wrote: > > On 26 Jan 2010, at 13:37, Jeff Schnitzer wrote: > > > I can't resist a conversation about framework design philosophy :-) > > > Oh go on then. Just a quickie. > > > This sort of binding (property of List<Photo>) can be convenient in > some applications, and as a longtime Hibernate user I got used to > working like this. But I don't like this abstraction in AppEngine. > Yes, for some apps you might be able to remove the "pollution" of > framework classes like Key (or OKey), but it comes with a price. > > > Twig and Objectify operate at very different levels of abstraction. With > Objectify you code at a lower level very aware of what is happening at the > datastore level. It involves more work but, as you point out, if something > goes wrong - it goes wrong in your own code where you are in a better > position to handle it. > > With Twig you operate at a higher level that makes the persistence layer > almost completely transparent. One major advantage of this is that you can > change the way the data is stored (i.e. embedded or separate entity) without > changing your code. Making such a change with Objectify means you need to > rewrite your reference handling code yourself. > > > A one-to-many relationship between Album and Photo has several > "standard" representations in AppEngine: > > * The Photo could have a Key property pointing to Album > > * The Photo could have a parent ancestor in its Key which points to the > Album > > * The Album entity could have a List<Key> property pointing to its Photos > > Each choice has a dramatic impact on performance, what can be done in > a transaction, and how you do queries that simply cannot be glossed > over or abstracted away. > > > This is why you configure what type of relationship is used using: @Embed, > @Entity(PARENT), @Entity(CHILD) or @Entity(INDEPENDENT) > > So you have the flexibility to choose configuration _without_ rewriting > your code. Very important difference. > > Currently the first type of representation is not an option. I do want to > add this as it makes very large collections that change often much more > efficient. When it is added you could reconfigure your data schema by > changing a single annotation. Such a change in Objectify would require the > developer to rewrite their entire data layer > > Which does the List<Photo> represent? > Furthermore, is List<Photo> a proxy or did the photos get fetched > along with the Album? Can I serialize the Album or do I need to > detach it? > > > Yes instances are just normal POJOs so no problems serializing. I do this > myself with GWT. > > Currently, lazy references are not supported... its a very important > feature on the TODO list. > > > Even worse, there are also two more possible representations: > > * The Photo could have a Key property (or ancestor) pointing to an > Album that does not exist > > > An inconsistent datastore is a problem with any framework - including > Objectify. The trick is to use transactions where possible whenever working > on an entity group to avoid getting this situation in the first place. > > * The Album could have a List<Key> property, and some of the Keys > could point to Photos that do not exist > > > As above. An exception would be thrown saying which property on what > object could not be found. > > Maybe these are degenerate cases, maybe not, but you'll never be able > to completely avoid them. RDBMSes have transactions and referential > integrity constraints that guarantee these later two cases can't > happen. Not so in AppEngine. You're just one > DatastoreTimeoutException away from having to deal with this situation > in your code. > > > If your data is inconsistent you have a problem - whether the framework > throws an exception (as in Twig) or if you receive a null back from a finder > method (as in Objectify) there is really not much difference. You still > have to clean up the mess. > > This is the big mess that makes JDO on Appengine so complicated, > possibly even more complicated than it is on an RDBMS. On the other > hand... if you simply expose the Key (or OKey), the developer does a > little more work but doesn't have to figure out all the configuration. > Without proxies, all entities are serializable and GWT-able without > any special consideration. > > > I think that for simple cases and small data models working with Keys and > handling the references yourself is fine. When things get more complicated > it is easier to reconfigure how the data is actually stored if you can > simply change a configuration option in one place. > > Actualy, JDO doesn't even offer all the necessary configuration > options, which is probably why you end up seeing Key a lot as > properties in JDO sample code. > > So.... while it seems like you might be able to keep Key and other > framework classes out of your entities... for many applications I > don't think it's realistic, and for most, I don't think it's a good > idea. > > IMHO, of course. > > > Obviously we agree to disagree on this point :) I much prefer letting he > framework handle repetitive boiler plate code with minimal configuration. > > Another feature only supported by Twig is embedded collections - this > allows > > you to do a single query for Albums containing a particular photo for > > example. In JDO, Objectify or any of the others this requires multiple > > queries. You configure it with a single Embed annotation like this: > > > We like this feature and are assimilating it now :-) > > > Nice one. It has honestly increased the performance of some queries by a > factor of 10 at least. > > Jeff > > > John > > -- > 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]<google-appengine-java%[email protected]> > . > For more options, visit this group at > http://groups.google.com/group/google-appengine-java?hl=en. > -- 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.
