EntityManager не видит изменений, внесенных в другие транзакции - PullRequest
2 голосов
/ 11 декабря 2010

Я пишу какое-то приложение для GlassFish 2.1.1 (насколько я знаю, JavaEE 5, JPA 1.0). У меня есть следующий код в моем сервлете (который я в основном позаимствовал из некоторого примера в Интернете):

@PersistenceContext(name = "persistence/em", unitName = "pu")
private EntityManager em;

@Resource
private UserTransaction utx;

@Override
protected void doPost(...) {
    utx.begin();
    . . . perform retrieving operations on em . . .
    utx.rollback();
}

web.xml содержит следующее:

<persistence-context-ref>
    <persistence-context-ref-name>persistence/em</persistence-context-ref-name>
    <persistence-unit-name>pu</persistence-unit-name>
</persistence-context-ref>   

Проблема в том, что они не видят изменений, которые были сделаны в другой внешней транзакции. Грубо говоря, я делаю запрос к сервлету из веб-браузера, просматриваю данные, выполняю некоторые DML в консоли SQL, перезагружаю страницу сервлета - и он не показывает никаких изменений. Я пытался использовать много комбинаций em.flush, utx.rollback и em.joinTransaction, но, похоже, это не принесло пользы.

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

Ответы [ 3 ]

2 голосов
/ 11 декабря 2010

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

Если вы хотите увидеть изменения, вам придется обновить кеш, и в этом случае все сущности будут удалены из кеша. Конечно, вам нужно знать, когда это сделать (после завершения другой транзакции), иначе вы по-прежнему будете видеть неоднозначные объекты. Если это ваша бизнес-потребность, то JPA, возможно, не очень подходит для вашей проблемной области.

Связанный:

  1. Кэшируются ли сущности в jpa по умолчанию?
  2. Аннулирование сеанса JPA EntityManager
1 голос
/ 11 декабря 2010

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

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

Если у вашего процесса все время одновременное чтение / запись из разных источников, вам действительно могут понадобиться пессимистичные блокировки. Если у вас иногда есть пакетное обновление из внешнего источника, вы можете попытаться сообщить из этого пакетного задания вашему приложению JPA, что оно должно быть удалено. Возможно через веб-сервис или около того. Таким образом, вы не будете подвергаться пессимистическому снижению производительности блокировки все время.

Мудрый урок заключается в том, что синхронизация процессов может быть действительно сложной:)

0 голосов
/ 11 декабря 2010

Возможно, вам нужно зафиксировать транзакцию, выполненную в консоли SQL.

...