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 241 other followers

  • Sleepless Nights…

    October 2009
    S M T W T F S
    « Sep   Nov »
     123
    45678910
    11121314151617
    18192021222324
    25262728293031
  • Blog Stats

    • 865,600 hits

AppEngine JDO example #1: retrieve an object by ID

Posted by David Chandler on October 30, 2009

This is the first of a series of posts that will demonstrate a variety of JDO mappings and queries with AppEngine.

For starters, let’s retrieve an object from the Datastore given its ID. Here’s the User object in our domain model:

package com.roa.client.domain;

import java.io.Serializable;

import javax.jdo.annotations.IdGeneratorStrategy;
import javax.jdo.annotations.IdentityType;
import javax.jdo.annotations.PersistenceCapable;
import javax.jdo.annotations.Persistent;
import javax.jdo.annotations.PrimaryKey;

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User implements Serializable
{
	private static final long serialVersionUID = -1126191336687818754L;

	@PrimaryKey
	@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
	private Long id;
	@Persistent
	private String firstName;
	...
}

Now we want to retrieve a User object given the ID property obtained from getId(). Easy enough, you think, as the JDO PersistenceManager provides a method for this:

// Doesn't quite work
User attachedUser = (User) getPM().getObjectById(userId);

But there’s a catch. Confusingly, the ID needed by getObjectById is a JDO ID, not the object property named “id” that we’ve annotated as an IDENTITY. You can get the JDO ID one of two ways. Whenever the object is attached, such as just after you’ve called makePersistent() on it, you can call persistenceManager.getObjectId(obj) and keep it in a safe place for later use. Alternatively, you can use a JDO helper method at any time to get the JDO ID from the object ID:

		 // Must obtain the JDO ID first
		 Object idInstance = getPM().newObjectIdInstance(User.class, user.getId());
		 User attachedUser = (User) getPM().getObjectById(idInstance);

Fortunately, if you know the object’s class, there’s a 2-arg getObjectById that does take the object’s primary key property:

User attachedUser = getPM().getObjectById(User.class, u.getId());

Of course, you can always just run a normal query on the object’s ID property, but it’s a bit ugly because the simplest query syntax always returns a Collection and we assume here that there will be only one matching object.

		Query q = getPM().newQuery(User.class, "id == :userId");
		List<User> users = (List<User>) q.execute(u.getId());
		User attachedUser = users.get(0);

Better to let the query language know that we expect a unique object:

		Query q = getPM().newQuery(User.class, "id == :userId");
		q.setUnique(true);
		User attachedUser = (User) q.execute(u.getId());

Finallly, there’s the low-level Datastore API:

		Key key = KeyFactory.createKey(User.class.getSimpleName(), u.getId());
		Entity entity = DatastoreServiceFactory.getDatastoreService().get(key);
Advertisements

5 Responses to “AppEngine JDO example #1: retrieve an object by ID”

  1. timo said

    Thanks for posting this useful example.

  2. yoyo said

    3Q very much!

  3. Vimal said

    Hello David,
    I just landed your website through a search on good tutorial on getObjectById in JDO.
    I am stuck in a GAE-Java web app I am developing to send mails to user of my app and then track them (mail view and web view via different URLs). Will be thankful for any help/guidance.

    Is it possible that same code to fetch an object from two different location in an app can behave differently. In my app, Worker URL of a task can easily fetch CONTACT object using the eMailID (annotated with @PrimaryKey, type String in CONTACT class). But when I try to fetch the same object using eMailId from a JSP (meant to track web view of the mail), it throws error. The only difference is – in first case eMailId is taken as a list from CONTACT objects while in second it is taken from RECIPIENT objects (stored as String – not primary key).

    I tried these options – Normal query on eMail field, getObjectById with String mailId as well as with Key (generated using KeyFactory) but nothing seems to be working.

    Please guide.

    Regards
    Vimal

  4. luis said

    tengo una duda como se generan llaves compuesta es decir que en mi clase tenga dos atributos con llave primarias

  5. Johnny Wu said

    I found something really “interesting”…not sure if I did something wrong or it’s a feature that’s not covered here:

    I have an entity with a primary key in Key type:
    @PrimaryKey
    @Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
    //@Persistent
    private Key objectID;

    When I called getObjectByID(MyObject.class, object.getID()), the code jumps out of the try statement and lands in the final statement.

    However, when I invoked the same call using the “Key” (or OID) value, it returns the actual object.

    The “tricky” thing is I can’t invoke anything to obtain the “Key” value for the object….or can I?

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: