TurboManage

David Chandler's Journal of Java Web and Mobile Development

  • David M. Chandler


    Web app developer since 1994 and former Developer Advocate with Google now residing in Colorado. Besides tech, I enjoy landscape photography and share my work at ColoradoPhoto.gallery.

  • Subscribe

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 242 other followers

  • Sleepless Nights…

    November 2009
    S M T W T F S
    « Oct   Dec »
    1234567
    891011121314
    15161718192021
    22232425262728
    2930  
  • Blog Stats

    • 849,257 hits

Key fields are not retrieved by default

Posted by David Chandler on November 6, 2009

I’ve noticed that AppEngine does not populate Key fields by default when querying. I’m sure it’s documented, but I can’t remember where. At any rate, you can annotate with defaultFetchGroup to resolve this. Same goes for properties of type Text and Blob.

...
import com.google.appengine.api.datastore.Key;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class PrayerItem implements Serializable
{
	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Long id;
	@Persistent(defaultFetchGroup="true")
	private Key list;
	...

}

In the case of owned relationships, where a property is represented by its actual domain class rather than a Key, it is also necessary to use defaultFetchGroup=”true”. Even though owned properties are in the same entity group and are therefore eligible for inclusion in a transaction, the AppEngine Datastore doesn’t allow joins, so owned relationships are not returned in the initial query. When you set defaultFetchGroup=”true” on an owned property, you will get this warning:

WARNING: Meta-data warning for com…your_owned_property_name: The datastore does not support joins and therefore cannot honor requests to place child objects in the default fetch group.  The field will be fetched lazily on first access.  You can modify this warning by setting the datanucleus.appengine.ignorableMetaDataBehavior property in your config.  A value of NONE will silence the warning.  A value of ERROR will turn the warning into an exception.

Lazy fetching does work as described in the message.

9 Responses to “Key fields are not retrieved by default”

  1. […] relationship. This was not correct, as AppEngine Datastore never allows joins. I’ve updated the original post […]

  2. Rusty Wright said

    What do you do if the persistence manager is closed? Doesn’t the lazy fetch only work if the persistence manager is still open? I’m using spring and my service layer has spring’s @Transactional on its classes and spring closes the persistence manager when the methods return.

    • Good clarification, thanks. Lazy fetching only works as long as the PM is open. Therefore, if you need to return a fully populated object graph to the client, you must call the getters for the joined fields before closing the PM. Typically, this means within the same service method that initiated the query.

  3. Chris said

    I have found that the defaultFetchGroup=”true” does work as described on app engine. I have also found in the documentation where it lays out an exact example of using this syntax.

    http://code.google.com/appengine/docs/java/datastore/jdo/relationships.html

    Child objects are loaded from the datastore when they are accessed for the first time. If you do not access the child object on a parent object, the entity for the child object is never loaded. If you want to load the child, you can either “touch” it before closing the PersistenceManager (e.g. by calling getContactInfo() in the above example) or explicitly add the child field to the default fetch group so it’s retrieved and loaded with the parent:

    Employee.java

    import ContactInfo;

    // …
    @Persistent(defaultFetchGroup = “true”)
    private ContactInfo contactInfo;

    The downside is I still get the Warning: Meta-data message when GAE executes the query. Is the documentation wrong or should the warning be written up as a bug?

    • Thanks, Chris. App Engine has come a long way in the 17 months since I wrote this, and shortly after, I switched from JDO to Objectify, so I’m not in the loop on JDO issues now.

  4. branflake2267 said

    How do you like objectify compared to JDO?

  5. branflake2267 said

    For those who are having this problem even though you have deeper children you’ll need to modify the jdoconfig.xml file and change the value to 2. If you have parent child relationship like myjdoclass(1)/myjdoclass(2)/myjdoclass(3)… you need to set the depth. I’m assuming “touch” means to write?

    /* file: jdoconfig.xml */

    This is noted in documentation: http://code.google.com/appengine/docs/java/datastore/jdo/relationships.html#Owned_One-to-One_Relationships – look for “touch”

    The documentation isn’t entirely clear what is going on with owned child collection relationships. Thanks for documenting this David because saved me a ton of time.

    Brandon Donnelson
    http://gwt-examples.googlecode.com

  6. branflake2267 said

    Oops the property disappeared under the file above, thinking it was html.

    /* file jdoconfi.xml */
    property name=”datanucleus.maxFetchDepth” value=”2″ – (add the greaterthan and less then…)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: