2010-03-08 3 views
8

Проект, над которым я работаю, использует Spring 2.5 & JPA с Hibernate в качестве поставщика.Invalidating JPA EntityManager session

Мои классы DAO расширяют JpaDaoSupport, поэтому я получаю свой JpaTemplate с помощью метода getJpaTemplate().

Базовая база данных может быть изменена либо моим приложением, либо сторонним приложением.

Когда приложение сторонних разработчиков изменяет базу данных (в основном изменения данных конфигурации), мне необходимо предоставить пользователю моего приложения способ аннулировать все сессии JPA и перезагрузить новые данные (т. Е. Аннулировать все сеансы спящего режима в задний план). Это должно быть «видимо» всеми одновременными пользователями моего приложения.

Как я могу это сделать?

ответ

21

Есть два уровня кэшей:

  • первый уровень является собственный кэш EntityManager в.

    Вы можете либо refresh на одном объекте, и он будет перезагружен из базы данных, либо вы можете clear сам менеджер сущности, и в этом случае все сущности удаляются из кеша. Нет никакого способа с JPA до evict only one specific entity из кеша. В зависимости от используемой вами реализации вы можете сделать это, например. Метод Hibernate evict.

  • Кэширование второго уровня - это глобальный кэш.

    JPA 1.0 не обеспечивал поддержку кэша второго уровня. Затем вам нужно полагаться на основную конкретную реализацию или отключить ее. JPA 2.0 will address this issue с аннотацией @Cache и API кеша. Вы можете очистить кеш второго уровня, используя Hibernate-специфический API, например. SessionFactory.evict(...).

Дополнительные проблемы с кэшированием являются:

  • кэш запросов

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

  • Кластеризация

    Затем идет также утомительной проблему синхронизации кэшей между узлами в кластере. В этом случае это в основном зависит от используемой технологии кэширования, например. Кэш JBoss.

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

Я работал над системой, и многие обновления были сделаны без перехода в спящий режим, и мы наконец отключили кеш второго уровня.

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

+1

getJpaTemplate(). GetEntityManager(). Clear() сделал трюк. Благодаря! – dasp

1

С архитектурной точки зрения, это не очень хорошая идея, чтобы позволить другому приложению обойти всю вашу бизнес-логику и модифицировать постоянные данные. Это делает землю под ногами вашего приложения дрожащей во многих отношениях :)

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

+1

Проблема недействительности кэша будет по-прежнему существовать, например, с пакетной обработкой и массовым обновлением. – ewernli

+2

Да, я бы сказал, выполняйте пакетную обработку таким образом, чтобы она запускала события для тех объектов, которые должны быть недействительными. Комбинация Spring Integration и Spring Batch идеально подходит для этого. Интересный разговор: http://www.infoq.com/presentations/Automating-Operations –