来自List的值有时会丢失或未在GAE数据存储区中使用JDO保存

时间:2015-10-30 12:23:38

标签: google-app-engine google-cloud-datastore jdo persistence-manager

我已经在google关于jdo数据存储区交易的文档中检查过,但找不到任何内容。 我的问题是我有一个带有ArrayList的实体,有时这些项目丢失或者没有正确保存。这是一个很大的问题,因为我在PRODUCTION中存在不一致和数据丢失。

父实体

@PersistenceCapable
public class Account

@Order(extensions = @Extension(vendorName = "datanucleus", key = "list-ordering", value = "key ASC"))
private ArrayList<Match> matches = new ArrayList<Match>();

@PersistenceCapable
public class Match

@Persistent
private ArrayList<Long> players = new ArrayList<Long>();

现在,我有一个cron任务,每15分钟更新一次玩家阵列列表。

PersistenceManager manager = PMFactory.get().getPersistenceManager();
List<Account> accounts = <<obtain all accounts>>
for (Account account : accounts) {
 Transaction tx = manager.currentTransaction();
 tx.begin();
 List<Long> players = account.getMatches.getPlayers();
    <<add or remove elements - players.remove()/players.add()>>
 tx.commit();
}
manager.close();

代码只是一个摘要。我尝试/捕捉并记录所有内容。没有异常提出任务,任务完成正常。我无法在本地重现此错误。 我有大约300个账户,每个账户可能有10个匹配。比赛的球员不超过20。 只有有时玩家列表没有正确更新......甚至他们失去了一些元素。大部分时间都有效。也许当第二个或第三个实例复活时?我应该关闭持久性管理器并为每个帐户获取一个新的吗? 我正在使用jdo 2.3。一直在使用这个应用程序4年,但现在我有更多的开放账户我有这个问题。请我绝望! :-( 非常感谢提前!

jdoconfig.xml

<jdoconfig xmlns="http://java.sun.com/xml/ns/jdo/jdoconfig"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:noNamespaceSchemaLocation="http://java.sun.com/xml/ns/jdo/jdoconfig">

   <persistence-manager-factory name="transactions-optional">
       <property name="javax.jdo.PersistenceManagerFactoryClass"
           value="org.datanucleus.api.jdo.JDOPersistenceManagerFactory"/>
       <property name="javax.jdo.option.ConnectionURL" value="appengine"/>
       <property name="javax.jdo.option.NontransactionalRead" value="true"/>
       <property name="javax.jdo.option.NontransactionalWrite" value="true"/>
       <property name="javax.jdo.option.RetainValues" value="true"/>
       <property name="datanucleus.appengine.autoCreateDatastoreTxns" value="true"/>
       <property name="datanucleus.appengine.datastoreEnableXGTransactions" value="true"/>
       <property name="datanucleus.appengine.singletonPMFForName" value="true"/>
   </persistence-manager-factory>
</jdoconfig>

的persistence.xml

<persistence xmlns="http://java.sun.com/xml/ns/persistence"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
        http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">

    <persistence-unit name="transactions-optional">
        <provider>org.datanucleus.api.jpa.PersistenceProviderImpl</provider>
        <properties>
            <property name="datanucleus.NontransactionalRead" value="true"/>
            <property name="datanucleus.NontransactionalWrite" value="true"/>
            <property name="datanucleus.ConnectionURL" value="appengine"/>
        </properties>
    </persistence-unit>
</persistence>

1 个答案:

答案 0 :(得分:0)

我找到了让它发挥作用的方法。我不确切知道哪条线正常工作,或者它是否完整:

PersistenceManager manager = PMFactory.get().getPersistenceManager();// get instance of PM
List<Account> keys = <<obtain all accounts KEYS>> //get only KEYS(before I was getting all accounts and not by their keys)
manager.close(); // close PM

for (Key key : keys) {
  manager = PMFactory.get().getPersistenceManager();// get instance of PM for each account:  Is this necessary?? should I use the same PM as before?? 
  Account account = dao.getAccount(key);
  List<Long> players = account.getMatches.getPlayers();
    <<add elements(players.add()) or do nothing depending on business logic>>               
  manager.flush(); //flush: is this necessary??
  manager.close(); // close PM for each account
}

这段代码似乎有效。我不知道它能使它工作的是关闭并打开每个账户的PM,或者获得KEYS然后通过其KEY获得每个账户或在关闭PM之前刷新。 因为我只能在PRODUCTION中重现这个错误,所以我无法测试是什么使它工作,什么是不必要的。我知道这段代码有效。