Подтвердить что ты не робот

Обязательные записи JDO не применяются к локальному HRD HRE или, возможно, к повторной операции

Я использую JDO 2.3 в приложении. Я использовал хранилище данных Master/Slave для локального тестирования и недавно переключился на использование хранилища данных HRD для локального тестирования, а части моего приложения ломаются (что и следовало ожидать). Одна часть приложения, в которой происходит нарушение, заключается в том, что он быстро отправляет много писем - это из-за 1-секундной лимитированной вещи, которая не срабатывает при исключении параллельной модификации.

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

Но странно, что происходит. Некоторые из записей, которые должны быть успешными (те, которые НЕ получают исключение параллельной модификации) также терпят неудачу, даже если этап фиксации завершен, и запрос возвращает мой код успеха. Я вижу из журнала, что повторные запросы работают нормально, но эти другие запросы, которые, кажется, были совершены с первой попытки, я думаю, никогда не применялись ". Но из того, что я прочитал о фазе Apply, снова писать тот же объект должен заставить применить... но это не так.

Далее следует код. Некоторые примечания:

  • Я пытаюсь использовать автоматическое кеширование JDO. Так вот где JDO использует memcache под обложками. Это фактически не работает, если вы не обернете все транзакции.
  • все запросы выполняются, это чтение строки из объекта, изменение части строки и сохранение этой строки для объекта. Если эти запросы не были в транзакциях, у вас, конечно, проблема с "грязным чтением". Но с транзакциями изоляция должна находиться на уровне "сериализуемого", поэтому я не вижу, что происходит здесь.
  • изменяемый объект является корневым объектом (не в группе)
  • У меня есть транзакции между группами.

Соответствующий код (это упрощенная версия):

PersistenceManager pm = PMF.getManager();
Transaction tx = pm.currentTransaction();
String responsetext = "";
try {
    tx.begin();
    // I have extra calls to "makePersistent" because I found that relying
    // on pm.close didn't always write the objects to cache, maybe that
    // was only a DataNucleus 1.x issue though
    Key userkey = obtainUserKeyFromCookie();
    User u = pm.getObjectById(User.class, userkey);
    pm.makePersistent(u); // to make sure it gets cached for next time
    Key mapkey = obtainMapKeyFromQueryString();
    // this is NOT a java.util.Map, just FYI
    Map currentmap = pm.getObjectById(Map.class, mapkey);
    Text mapData = currentmap.getMapData(); // mapData is JSON stored in the entity
    Text newMapData = parseModifyAndReturn(mapData); // transform the map
    currentmap.setMapData(newMapData); // mutate the Map object
    pm.makePersistent(currentmap); // make sure to persist so there is a cache hit
    tx.commit();
    responsetext = "OK";
} catch (JDOCanRetryException jdoe) {
    // log jdoe
    responsetext = "RETRY";
} catch (Exception e) {
    // log e
    responsetext = "ERROR";
} finally {
    if (tx.isActive()) {
        tx.rollback();
    }
    pm.close();
}
resp.getWriter().println(responsetext);

ОБНОВЛЕНИЕ. Я уверен, что знаю, почему это происходит, но я все равно награжу награду всем, кто сможет ее подтвердить.

В принципе, я думаю, проблема заключается в том, что транзакции на самом деле не реализованы в локальной версии хранилища данных. Ссылки:

https://groups.google.com/forum/?fromgroups=#!topic/google-appengine-java/gVMS1dFSpcU https://groups.google.com/forum/?fromgroups=#!topic/google-appengine-java/deGasFdIO-M https://groups.google.com/forum/?hl=en&fromgroups=#!msg/google-appengine-java/4YuNb6TVD6I/gSttMmHYwo0J

Поскольку транзакции не реализованы, откат по существу не работает. Поэтому я получаю грязное чтение, когда две транзакции пытаются изменить запись в одно и то же время. Другими словами, A считывает данные, а B считывает данные одновременно. Попытка изменить данные, а B пытается изменить другую часть данных. А пишет в хранилище данных, затем пишет B, стирая изменения A. Затем B "откатывается" с помощью движка приложения, но поскольку откаты являются "нет-op" при работе в локальном хранилище данных, изменения B остаются, а A нет. Между тем, поскольку B - это поток, который выбрал исключение, клиент повторяет B, но не повторяет A (так как A предположительно является транзакцией, которая преуспела).

4b9b3361

Ответ 1

Может быть, плохая новость для вас, я оставил JDO, и я использую Objectify и в некоторых местах прямо datanucleus. У меня есть идеальный контроль над моей настойчивостью, которая является лучшим вариантом исполнения и дизайна (если вы думаете в долгосрочной перспективе).

Поскольку db не-sql, существуют структурные изменения в отношении JPA, JDO и стандартных допущений:

Используя собственный API-интерфейс datanucleus, вы можете делать то, что не входит в стандартную JPA или даже в Objectify: пример, который я использовал, - динамически создавать столбцы

В GAE транзакции нет, есть что-то, что иногда может выглядеть как транзакция (группы сущностей). Поэтому использование родного API позволит вам делать такую ​​непродуманную гимнастику.

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