views:

80

answers:

2

I've got this code (Java, GAE):

// Much earlier:
playerKey = KeyFactory.keyToString(somePlayer.key);

// Then, later...
PersistenceManager pm = assassin.PMF.get().getPersistenceManager();

Key targetKey = KeyFactory.stringToKey(playerKey);
Query query = pm.newQuery(Player.class);
query.setFilter("__key__ == keyParam");
query.declareParameters("com.google.appengine.api.datastore.Key keyParam");
List<Player> players = (List<Player>) query.execute(targetKey); // <-- line 200

which generates this error:

javax.jdo.JDOFatalUserException: Unexpected expression type while parsing query.  Are you certain that a field named __key__ exists on your object?
    at org.datanucleus.jdo.NucleusJDOHelper.getJDOExceptionForNucleusException(NucleusJDOHelper.java:354)
    at org.datanucleus.jdo.JDOQuery.execute(JDOQuery.java:252)
    at myapp.Player.validPlayerWithKey(Player.java:200)
    // [etc., snip]

But I'm not sure what it wants. I'm trying to search on the JDO id field, which I I thought I read had the special name __key__, in the documentation.

I've tried it with both

query.setFilter("__key__ == keyParam");

and

query.setFilter("ID == keyParam");

with the same results. So, what am I doing wrong? Or, more importantly, how do I do it correctly?

Thanks!

Edit: For completeness's sake, here is the final, working code (based on Gordon's answer, which I have accepted as correct):

Player result = null;
if (playerKey == null)
{
    log.log(Level.WARNING, "Tried to find player with null key.");
}
else
{
    PersistenceManager pm = assassin.PMF.get().getPersistenceManager();

    try {
        result = (Player) pm.getObjectById(Player.class, playerKey);
    } catch (javax.jdo.JDOObjectNotFoundException notFound) {
        // Player not found; we will return null.
        result = null;
    }

    pm.close();
}

return result;
A: 

I would recommend you to use the JPA ( http://code.google.com/appengine/docs/java/datastore/usingjpa.html ) to access your data in GAE, it has the very important advantage that you can use the widely known and documented JPA standard (and its JPAQL querying language) to do this kind of things, in portable way (if you stick to the JPA standard, your code will work for GAE, for Hibernate or with EclipseLink without modification)

Luxspes
The JDO standard is a widely known standard too, and you can use the same JDO code with other JDO implementations (if you omit the Google specifics), as clearly demonstrated in the original videos from Google campfire of April 2009.
DataNucleus
Yes, but JPA has been IMO far more successful from an adoption pov.
Luxspes
The point is that the user asked a question, and he is using JDO. He didn't ask what API would you recommend, simply how do I do this thing (with JDO, what he has now). "Ahh, you can do it with JPA, but then you have to change all of your persistence code" ... not really answering him that way ;-)
DataNucleus
+2  A: 

If your objective is to get an object by key, then you should use the PersistenceManager's getObjectByID() method. More details here.

As an aside, trying to construct a query to get something by it's key is something you shouldn't need to do. Although this is how you would work with an SQL database, the Google Data Store does things differently, and this is one of those cases where rather than go through the trouble of constructing a query, Google App Engine lets you get what you want directly. After all, you should only have one entity in the database with a particular key, so there's nothing in the rest of the machinery of a GQL query that you need in this case, hence it can all be skipped for efficiency.

Gordon Worley
Works like a charm. I stole your answer (but gave a shout-out) over on this similar SO question: http://stackoverflow.com/questions/3438586/google-app-engine-filter-by-id , hope that's ok. Thanks!
Olie