使用DataNucleus JDO在Google App Engine中更新子对象

时间:2011-02-13 18:42:48

标签: java google-app-engine google-cloud-datastore entity jdo

我花了几个小时试图解决这个问题,尽管尝试了几个建议,我似乎无法让我的孩子实体更新。我已经广泛地查看了GAE文档,并且我尝试将事务放在事务中,尝试将它们作为“拥有”对象并使它们成为“默认获取组”的一部分。在运行下面的虚拟“populateDatastore”方法后,对象在数据存储区中正确保留,我可以从数据存储区中检索它们而没有任何问题。当我进行更改时,这些更改不会保留,虽然我使用setter方法,因此JDO会接收更改。我不是Java专家,所以我可能会做一些非常明显错误的事情而且我没有看到它。

父对象

@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
}

子对象

@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
}

我有几种方法可以检索和保存对象。

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

最后,我有一个虚拟方法将一些数据放入数据存储区进行测试。我在子列表中添加了几个子项,但为了简洁起见,我删除了许多冗余代码。我也坚持使用几个父对象。

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

3 个答案:

答案 0 :(得分:1)

我不确切知道“PMF.get()”背后的实现是什么,但是如果你在每个get()上创建一个新的 PersistenceManagerFactory - 没有必要,你可以把它作为静态成员。 如果这不是问题,请尝试检查您是否使用相同的 PersistenceManager 来检索和更新数据对象:意味着只有一次调用 PMF.get()。getPersistenceManager()用于整个操作。如果您需要查询对象,然后使用其他 PersistenceManager 将其保留,则应detach

答案 1 :(得分:0)

我遇到的问题是我的父对象主键是&#34; Key&#34;宾语。改为长期工作。不知道究竟是什么问题以及它是如何解决问题的,因为我是android和gae的新手

答案 2 :(得分:0)

我添加了以下内容并解决了我的问题:

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