Объект JPA обновляется только после завершения метода - PullRequest
3 голосов
/ 25 октября 2011

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

@Inject EntityDao entityDao;

@Asynchronous
public Future<String> doSomething (MyEntity p_myEntity) {

    MyEntity myEntity = entityDao.merge(p_myEntity); // change from detached to attached
    // em.contains(myEntity) returns true

    myEntity.setName("Joe 1"); // newer set in database
    // A System.out.println(myEntity.getName()) does say "Joe 1"

    try {
        Thread.sleep(20*1000);
    } catch () ...etc

    myEntity.setName("Joe 2"); // newer set in database
    // A System.out.println(myEntity.getName()) does say "Joe 2"

    try {
        Thread.sleep(20*1000);
    } catch () ...etc

    myEntity.setName("Joe 3"); // only one set in database

    return new AsyncResult<>("done");
}

Редактировать : Так что, благодаря ПедроКовальски, я лучше понимаю проблему и переформулирую.

Во время выполнения вышеописанного метода у меня есть два способа проверить, действительно ли myEntity.setName () действительно изменилось:

  • Во время сна () я проверяю базу данных, если имя изменено
  • На веб-странице отображается список объектов MyEntity (с именами), этот список обновляется каждые 2 секунды.

Оба приведенных выше метода указывают, что значения "Joe 1" и "Joe 2" являются более новыми в базе данных. Только после выполнения метода doSomething () в базу данных помещается набор фамилий (Joe 3).

Итак, мой вопрос: почему значения «Джо 1» и «Джо 2» не заносятся в базу данных, а в базу данных заносится только последнее значение?

Ответы [ 2 ]

5 голосов
/ 26 октября 2011

Если вы используете транзакции JTA, граница транзакции распространяется от начала метода до его конца.

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

Вот почему вы не увидите «Joe 1» (это значение изменяется только в T1) из любой транзакции, кроме T1. Вы можете увидеть «Джо 2» только после завершения методов (коммит T1).

EntityManager # flush () синхронизирует данные с базовой базой данных, но не фиксирует их . Для более подробной информации вы можете увидеть эту тему: http://www.java.net/node/665442#comment-678155

В этом случае я вижу три решения:

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

  2. Пессимистическая блокировка может заблокировать данные на время модификации. В этом случае ваша транзакция T2 не будет работать с данными, пока T1 не завершится.

  3. Наконец - самая простая ситуация (если это возможно) просто разделить ваш метод на более мелкие куски.

НТН.

0 голосов
/ 26 февраля 2013

Итак, мой вопрос: почему значения «Джо 1» и «Джо 2» не заносятся в базу данных, а в базу данных заносится только последнее значение?

  • Данные записываются в базу данных во время em.flush ().Данные видны другим пользователям / контекстам персистентности, когда транзакция зафиксирована.

  • Вы не выполняете ручную очистку базы данных с помощью em.flush (), поэтому em.flush () автоматическиВызывается, когда транзакция фиксируется.

  • Транзакция фиксируется в конце вашего метода, то есть, когда происходит сброс, то есть «Joe3» записывается в БД и также фиксируется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...