EntityManager не видит изменений, внесенных в другие транзакции
Я пишу приложение для 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 ответа
Реализация JPA поддерживает кэш сущностей, к которым был получен доступ. Когда вы выполняете операции в другой транзакции без использования JPA, кэш больше не обновляется, и, следовательно, вы никогда не увидите внесенные в него изменения.
Если вы хотите увидеть изменения, вам придется обновить кеш, и в этом случае все сущности будут удалены из кеша. Конечно, вам нужно знать, когда это сделать (после завершения другой транзакции), иначе вы по-прежнему будете видеть неоднозначные объекты. Если это ваша бизнес-потребность, то JPA, возможно, не очень подходит для вашей проблемной области.
Связанные с:
Как говорит axtavt, вам нужно зафиксировать транзакцию в консоли. Предполагая, что вы сделали это, также возможно, что данные все еще кэшируются с помощью PersistenceManager (или базовой инфраструктуры).
Чтобы избежать проблем с кэшированием, вы можете выселить вручную (что может быть непросто, поскольку вы должны знать, когда нужно выселить), или вы можете перейти к пессимистической блокировке. Пессимистическая блокировка может оказать огромное влияние на производительность, но если у вас есть несколько независимых подключений к базе данных, у вас может не быть выбора.
Если у вашего процесса все время одновременное чтение / запись из разных источников, вам действительно могут понадобиться пессимистичные блокировки. Если у вас иногда есть пакетное обновление из внешнего источника, вы можете попытаться сообщить из этого пакетного задания вашему приложению JPA, что оно должно быть исключено. Возможно через веб-сервис или около того. Таким образом, вы не будете подвергаться пессимистическому снижению производительности блокировки все время.
Мудрый урок заключается в том, что синхронизация процессов может быть действительно сложной:)
Возможно, вам нужно совершить транзакцию, сделанную в консоли SQL.