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);
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 is to let the query language know that we expect a unique object, but then we have to write out the whole query and declare our imports one way or another.
Query q = getPM().newQuery("SELECT UNIQUE FROM com.roa.client.domain.User WHERE id == :userId");
User attachedUser = (User) q.execute(u.getId());
All things considered, calling the JDO helper method to get a JDO ID from an object ID may be the least painful.