Значения из списка иногда теряются или не сохраняются с помощью JDO в хранилище данных GAE
Я проверил везде, даже в документации Google по транзакциям jdo datastores, но ничего не смог найти. Моя проблема в том, что у меня есть объект с ArrayList, и иногда элементы теряются или сохраняются неправильно. Это огромная проблема, поскольку у меня возникают несоответствия и потеря данных в ПРОИЗВОДСТВЕ.
Родительский объект:
@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 ответ
Я нашел способ заставить это работать. Я не знаю точно, какая строка заставляет это работать или это целое:
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, я не могу проверить, что заставляет ее работать, а что нет необходимости. Я знаю, что этот код работает.