Hibernate / Ehcache: извлечение коллекций из кэша 2-го уровня не синхронизировано с другими операциями чтения из БД - PullRequest
8 голосов
/ 01 октября 2009

У меня есть приложение, использующее JPA, Hibernate и ehcache, а также декларативное Spring сделки. Нагрузка на БД довольно высока, поэтому все кэшируется для ускорения работы, в том числе коллекции. Теперь не секрет, что коллекции кэшируются отдельно от сущностей, которые владеют ими, так что если я удаляю сущность, которая является элементом такого кэшированная коллекция, сохранить объект, который должен быть элементом одного, или обновить сущность такая, что она путешествует из одной коллекции в другую, я должен выполнить выселение от руки.

Поэтому я использую прослушиватель событий гибернации, который отслеживает вставленные, удаленные объекты или обновляется и сохраняет эту информацию для синхронизации транзакций, зарегистрированных в Spring Менеджер транзакций. Затем синхронизация выполняет выселение, как только транзакция совершена.

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

Как правильно синхронизировать этот материал?

Я пытался выполнить выселение в каждом из 4 методов TransactionSynchronization (который вызываются в разные моменты времени относительно завершения транзакции), это не помогло.

Ответы [ 3 ]

3 голосов
/ 02 октября 2009

По сути, вам нужно вызвать чтение из базы данных в случае, если коллекция находится в процессе или только что была удалена. Одним из способов сделать это было бы пометить коллекцию как грязную, как только был получен запрос на выселение, но перед вводом транзакции, чтобы изменить его. Любая параллельная транзакция проверит грязный флаг, и если он установлен в true, он должен получить данные из базы данных, в противном случае он может прочитать из кэша. Возможно, вам придется изменить параметры транзакций БД, чтобы параллельные транзакции блокировались до тех пор, пока тот, который обновляет данные, не завершит работу, чтобы из БД считывались правильные данные. После завершения транзакции вы можете сбросить грязный флаг на false.

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

0 голосов
/ 07 декабря 2009

Я думаю, вы должны ссылаться на эту ссылку: - Hibernate: очистить кэш 2-го уровня коллекции при каскадном удалении элементов видите, hibernate на самом деле не удаляет объект из кеша .. остальные вы можете получить ответ сверху ссылка

0 голосов
/ 02 октября 2009

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

Или я что-то упустил? Почему вы просто не можете обновлять коллекции?

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