Hi Chau, yes both Objectify and Twig replace JDO/JPA. I think that
Google would not release a non-standard datastore user-level API
because they could then be accused by many of "vendor lock-in". When
App Engine was launched there was a lot of concern about this.
On 26 Jan 2010, at 16:59, Chau Huynh wrote:
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]
.
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
.
--
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.