Не работает согласованное чтение в App-Engine JDO, возможно, кеширование? - PullRequest
5 голосов
/ 17 декабря 2011

Сегодня я впервые использую GWT и JDO. Я запускаю его с Eclipse в режиме локальной отладки.

Я делаю следующее:

    public Collection<MyObject> add(MyObject o) {
PersistenceManager pm = PMF.get().getPersistenceManager();
try {
    pm.makePersistent(o);
    Query query = pm.newQuery(MyObject.class);// fetch all objects incl. o. But o only sometimes comes...
List<MyObject> rs = (List<MyObject>) query.execute();
ArrayList<MyObject> list= new ArrayList<MyObject>();
for (MyObject r : rs) {
    list.add(r);
}
return list; 
} finally {
    pm.close();
}
}

Я уже установил <property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" /> в моем jdoconfig.xml. Должен ли я установить некоторые другие вещи транзакции в конфигурации? У кого-нибудь есть рабочий jdoconfig.xml? Или проблема где-то еще? Некоторое кеширование между ними?

РЕДАКТИРОВАТЬ: То, что я пытался:

  • Установка нетранзакционного чтения / записи в false
  • Использование одного и того же / другого PersistenceManager при вызове PMF.get().getPersistenceManager() несколько раз
  • Использование транзакций
  • ignoreCache = true в PersistenceManager
  • звонит flush и checkConsistency

jdoconfig:

    <persistence-manager-factory name="transactions-optional">
<property name="datanucleus.appengine.datastoreReadConsistency" value="STRONG" />
    <property name="javax.jdo.PersistenceManagerFactoryClass"
        value="org.datanucleus.store.appengine.jdo.DatastoreJDOPersistenceManagerFactory"/>
    <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"/>
</persistence-manager-factory>

Я, должно быть, упускаю что-то центральное здесь, потому что все подходы терпят неудачу ...

EDIT2: Когда я делю задание на две транзакции, журнал сообщает, что транзакция записи завершена, а затем начинается транзакция чтения. Но он не находит только что сохраненный объект. Это всегда говорит Level 1 Cache of type "weak" initialised также. Неделя плохая или хорошая?

Это примерно 30% запросов, которые идут не так ... Могу ли я быть ленивой проблемой загрузки запросов?

Ответы [ 3 ]

2 голосов
/ 20 декабря 2011

Франц, Согласованность чтения по умолчанию в JDO Config - СИЛЬНАЯ. так что, если вы пытаетесь приблизиться к нему в этом направлении, это никуда вас не приведет

Проверьте это, так как я думаю, что упоминается нечто похожее на сценарий, с которым вы сталкиваетесь, когда зафиксированные данные не возвращаются обратно в запросе. Он не является параллельным, как уже упоминалось, но он объясняет процесс фиксации.

http://code.google.com/appengine/articles/transaction_isolation.html

Кроме того, другим подходом будет запрос с использованием экстентов и выяснение, решает ли это конкретный вариант использования, который вы просматриваете, поскольку я полагаю, что вы вытаскиваете все записи в таблице.

РЕДАКТИРОВАТЬ:

Поскольку во фрагменте кода, который вы упомянули, он запрашивает всю таблицу. И если это то, что вам нужно, вы можете использовать экстент ... Чтобы использовать его, позвоните

Extent ext = getExtent(<Entity Class name>)

для одноэлементного объекта persistenceManager. Затем вы можете перебрать Экстент

Ознакомьтесь с документацией и найдите экстенты на странице здесь. http://code.google.com/appengine/docs/java/datastore/jdo/queries.html

2 голосов
/ 20 декабря 2011

Вызов метода makePersistent() не записывает данные в хранилище данных;закрытие PersistenceManager или фиксация изменений.Поскольку вы не сделали этого при выполнении запроса, вы получаете все объекты из хранилища данных, которое пока не включает объект, который вы только что вызвали makePersistent.

Прочитайте о состояниях объекта здесь: http://db.apache.org/jdo/state_transition.html

Есть два способа обойти это, вы можете поместить это в транзакцию, так как коммит записывает в хранилище данных (имейте в виду, что GAE 5 транзакция / ограничение типа сущности для транзакций) и фиксирует перед выполнением запроса;Пример использования транзакции ...

public Collection<MyObject> add(MyObject o) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    ArrayList<MyObject> list = null;
    try {
        Transaction tx=pm.currentTransaction();
        try {
            tx.begin();
            pm.makePersistent(o);
            tx.commit(); 
        } finally {
            if (tx.isActive()) {
                tx.rollback();
            }
        }

        Query query = pm.newQuery(MyObject.class);
        List<MyObject> rs = (List<MyObject>) query.execute();
        ArrayList<MyObject> list = new ArrayList<MyObject>();
        for (MyObject r : rs) {
            list.add(r);
        }
    } finally {
        pm.close();
    }

    return list; 
}

или вы можете закрыть диспетчер постоянства после вызова makePersistent для o, а затем открыть еще один, чтобы выполнить запрос.

// Note that this only works assuming the makePersistent call is successful
public Collection<MyObject> add(MyObject o) {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
        pm.makePersistent(o);
    } finally {
        pm.close();
    }

    pm = PMF.get().getPersistenceManager();
    ArrayList<MyObject> list = null;
    try {

        Query query = pm.newQuery(MyObject.class);
        List<MyObject> rs = (List<MyObject>) query.execute();
        list= new ArrayList<MyObject>();
        for (MyObject r : rs) {
            list.add(r);
        }

    } finally {
        pm.close();
    }

    return list; 
}

ПРИМЕЧАНИЕ: Я изначально говорил, что вы можете просто добавить o в список результатов перед возвратом;но это не очень разумно, поскольку в случае возникновения проблемы с записью o в хранилище данных;тогда возвращенный список не будет отражать фактические данные в хранилище данных.Выполнение того, что у меня сейчас (совершение транзакции или закрытие вечера, а затем получение другой), должно работать, поскольку для вашего datastoreReadPolicy установлено значение STRONG.

1 голос
/ 04 декабря 2014

Я столкнулся с той же проблемой, и это не помогло.Так как это, похоже, лучший результат в Google для "согласованности движка приложения jdo в затмении", я решил поделиться этим исправлением для меня!

Оказывается, я использовал несколько экземпляров PersistenceManagerFactory, что привело к некоторому странному поведению,Исправление состоит в том, чтобы иметь единственный элемент, к которому обращается каждый фрагмент кода.На самом деле это задокументировано правильно в руководствах по GAE, но я думаю, что его важность занижена.

Получение экземпляра PersistenceManager

Приложение взаимодействует с JDO с помощьюэкземпляр класса PersistenceManager.Вы получаете этот экземпляр путем создания экземпляра и вызова метода в экземпляре класса PersistenceManagerFactory.Фабрика использует конфигурацию JDO для создания экземпляров PersistenceManager.

Поскольку для запуска экземпляра PersistenceManagerFactory требуется время, приложение должно повторно использовать один экземпляр.Простым способом управления экземпляром PersistenceManagerFactory является создание одноэлементного класса-оболочки со статическим экземпляром следующим образом:

PMF.java

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManagerFactory;

    public final class PMF {
        private static final PersistenceManagerFactory pmfInstance =
            JDOHelper.getPersistenceManagerFactory("transactions-optional");

        private PMF() {}

        public static PersistenceManagerFactory get() {
            return pmfInstance;
        }
    }
...