Как поддерживать кэш EntityManager с помощью Hibernate в JBoss в согласованном состоянии?

StackOverflow https://stackoverflow.com/questions/1288085

Вопрос

Мы запускаем JBoss с гибернацией, и у нас возникла эта проблема.

Когда сеансовый компонент использует EntityManager для поиска объекта, он может уже существовать в кэше EntityManager, и его состояние может быть уже устаревшим.Если код использует такую сущность для принятия решений, он может принимать неправильные решения, которые приведут к ошибкам.

Вот примерный случай.

HTTP-запрос 1.Сеансовый компонент создает экземпляр сущности и сохраняет его с полем "A", для которого установлено значение 1.Сохраняемый объект получает ID = 4.

HTTP-запрос 2.Сессионный компонент ищет объект с идентификатором = 4, присваивает его полю "A" значение 2 и сохраняет его.

HTTP-запрос 3.Сессионный компонент ищет объект с ID = 4 и проверяет его поле "A".Если значение равно 1, это делает одно, если равно 2, это делает другое.

В случае, если EM в запросе 3 совпадает с тем, что указано в запросе 1, возникает нежелательное поведение.Я протестировал это и получил ок.10% случаев отказа.

Итак, вопрос в том, как этого избежать?Вызов em.refresh() или em.clear() каждый раз, когда я должен убедиться, что объект обновлен, кажется пустой тратой ресурсов.

Это было полезно?

Решение

Artem,

Это, по-видимому, повторяющийся тема среди ваших вопросов :-)

Хотя я понимаю, что ответы, которые вы получали раньше (включая мои), могут оказаться не такими, на какие вы надеялись, они не изменятся:

  • Entity Manager - это сеанс, подключенный к гибернации, и обычно он должен быть кратковременным. Здесь это хорошее объяснение единицы работы, транзакции и области применения, относящихся к сеансам гибернации, взгляните, если вы не видели этого раньше.
  • Если ваше приложение является последовательно держась за менеджеров организаций, вам необходимо серьезно подумать об изменении этой стратегии;если вы просто делаете это в нескольких местах, где вам действительно нужны длительные транзакции, чем при использовании refresh() такой метод, безусловно, является меньшим из всех зол.
  • В отличие от кэш второго уровня в случае кластеризованных реализаций кэш сеансового уровня не синхронизируется между различными сеансами (менеджерами сущностей). по замыслу и одновременные обновления одного и того же объекта обрабатываются с помощью оптимистичная блокировка обеспечивается гибернацией или блокировкой на уровне приложения.
  • Теоретически вы могли бы (при условии, что ваш доступ к ORM разделен достаточно хорошо) поддерживать свой собственный кэш (при необходимости кластеризуемый) объектов, принадлежащих различным менеджерам объектов;вам нужно будет соответствующим образом зарегистрироваться прослушиватели событий с каждым из них, чтобы синхронизировать ваш кэш.Однако я бы настоятельно рекомендовал отказаться от такого подхода - он не только довольно сложен в реализации и подвержен ошибкам, но и вы бы пошли вразрез с парадигмой Hibernate.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top