简体   繁体   中英

Updating child objects in Google App Engine using DataNucleus JDO

I have spent several hours trying to work this one out and I just can't seem to get my child entities to update despite trying several suggestions. I have looked at the GAE documents extensively and I have tried placing things in transactions, tried making them "owned" objects and making them part of the "default fetch group." The objects are correctly persisted in the datastore after running the dummy "populateDatastore" method below and I can retrieve them from the datastore with no issue. When I make changes, those changes are not persisted, although I am using the setter methods so JDO picks up the changes. I am not a Java expert, so I may be doing something really obviously wrong and I don't see it.

Parent object

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class Parent {
  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;

  @Persistent
  private String invitationCode;

  @Persistent(defaultFetchGroup = "true")
  private Child child;

  // additional ivars and getters and setters
}

Child object

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true")
public class Response {

  @PrimaryKey
  @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
  private Key key;

  @Persistent(mappedBy = "child")
  private Parent parent;

  // additional ivars and getters and setters
}

I have several methods to retrieve and save objects.

public void persistParent(Parent p, boolean closeSession){
  manager = PMF.get().getPersistenceManager();
  manager.makePersistent(p);

  if(closeSession) {
    manager.close();
  }
}

public Transaction beginTransaction() {
  int retries = 3;
  manager = PMF.get().getPersistenceManager();
  Transaction tx = manager.currentTransaction();

  try {
    tx.begin();
  }
  catch(com.google.apphosting.api.ApiProxy.CapabilityDisabledException e) {
    return null;
  }
  catch(Exception e) {
    return null;
  }
  return tx;
}

public boolean endTransaction(Transaction tx) throws Exception {
  int retries = 3;
  try {
    tx.commit();
  }
  catch(ConcurrentModificationException e) {
if (retries == 0) {
      throw e;
    }
--retries;
  }
  catch(com.google.apphosting.api.ApiProxy.CapabilityDisabledException e) {
    if (retries == 0) {
      throw e;
    }
--retries;
  }
  catch(Exception e) {
    if (retries == 0) {
      throw e;
    }
    --retries;
  }
  finally {
    if(tx.isActive()) {
      tx.rollback();
    }
  }

  manager.close();

  return true;
}

public List<Parent> getParentWithID(String code, boolean closeSession) {
  Query q = PMF.get().getPersistenceManager().newQuery(Parent.class);
  q.setFilter("code == codeParam");
  q.declareParameters("String invitationCodeParam");

  List<Invitation> results = null;
  try {
    results = (List<Parent>) q.execute(code);
  } 
  finally {
    if(closeSession) {
      q.closeAll();
    }
  }

 return results;
 }

Lastly, I have a dummy method to throw some data into the datastore for testing. I add several children to the children list but for brevity's sake, I have cut out a lot of the redundant code. I also persist several parent objects as well.

Child c = new Child(arg1, arg2, arg3);
c.setSomeIVarForChild(arg1);
p = new Parent(arg1, arg2, arg3);
p.getChildList().add(c);
rsvpDao.persistParent(p, true);

I don't know exactly what is the implementation behind "PMF.get()", but in case you are creating a new PersistenceManagerFactory on each get() - there is no need, you can just hold it as a static member. If this is not the problem, try checking if you are using the same PersistenceManager for retrieving and updating the data objects: meaning only one call to PMF.get().getPersistenceManager() for the entire operation. In case you need to query for objects and then persist them later using a different PersistenceManager , you should detach

Problem which I faced was my parent object primary key was "Key" object. Changing to to Long worked. Not sure what is the exact issue and how it solved the problem as I'm new to android and gae

I've added the following and it fixed my issue:

if(JDOHelper.getPersistenceManager(obj) != pm) {
    logger.error("JDOHelper.getPersistenceManager(obj) != pm  ->     JDOHelper.getPersistenceManager(obj)[" +     JDOHelper.getPersistenceManager(obj).toString() + "]"
                            + " pm[" + pm.toString() + "]");
                    detatchedJob =     JDOHelper.getPersistenceManager(obj).detachCopy(obj);
                    jobs.add(detatchedJob);
                } else {
                    detatchedJob = pm.detachCopy(obj);
                    jobs.add(detatchedJob);
                }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM