0

I'm writing a small application using GWT and JDOs to store persistent data. I've been trying to write a function that updates multiple JDO objects based on a query. Its body looks something like this:

PersistenceManager pm = getPersistenceManager();
try {
    q = pm.newQuery(MyObject.class, query);
    List<MyObject> objects = (List<MyObject>) q.execute();
    for (MyObject object: objects) {
        object.setMyField(newValue);
    }
    System.out.println(objects); //[1]
} finally {
    pm.close();
}

If I look at the output of the print statement at [1], the objects all have the correctly updated values. When I make an RPC to retrieve the updated objects, however, the values are the same as they were before the update method was called. If I check the datastore in the admin panel, the updates also do not appear.

All the other persistence behaviour in my application works fine (e.g. adding new objects, removing objects, querying objects), but I can't seem to figure out what's wrong here. Most of the resources I've found (like http://code.google.com/appengine/docs/java/datastore/jdo/creatinggettinganddeletingdata.html#Updating_an_Object) suggest that just having the PersistenceManager open should persist any changes you make to retrieved objects.

Any suggestions? I am truly baffled.

Thank you!

SOLUTION

PersistenceManager pm = getPersistenceManager();
try {
    q = pm.newQuery(MyObject.class, query);
    List<MyObject> objects = (List<MyObject>) q.execute();
    for (MyObject object: objects) {
        object.setMyField(newValue);
        JDOHelper.makeDirty(object, myField);
    }
} finally {
    pm.close();
}
cjm
  • 3,703
  • 1
  • 16
  • 18
  • Of course as soon as I post this I find the related post with the answer. I'll just leave this here: http://stackoverflow.com/questions/7486710/updating-objects-in-gae – cjm Feb 24 '12 at 01:07
  • Obviously that's not a real answer. You retrieve objects non-transactional, so they are in what state ? (JDOHelper.getObjectState(obj) tells you). Any setter will make that field dirty (read the log, it tells you). You then never start a new txn, hence any changes don't go to the DB (using GAE v2 plugin the pm.close will certainly flush all remaining changes). – DataNucleus Feb 24 '12 at 08:30

1 Answers1

1

The proper way to update JDOs is to use a transaction, e.g. (w/o proper handling)

PersistenceManager pm = getPersistenceManager();
try {
    q = pm.newQuery(MyObject.class, query);
    List<MyObject> objects = (List<MyObject>) q.execute();
    pm.currentTransaction().begin(); // <-------
    for (MyObject object: objects) {
        object.setMyField(newValue);
    }
    pm.currentTransaction().commit(); // <-------
    System.out.println(objects); //[1]
} finally {
    pm.close();
}

I'd recommend you do that for other all other update scenario including add/delete operations.

TheArchitect
  • 2,161
  • 1
  • 12
  • 16