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);