Кэширование сущностей JPA2 - PullRequest
       15

Кэширование сущностей JPA2

1 голос
/ 26 августа 2011

В существующем состоянии я использую bean-объект в области запросов JSF для выполнения всех моих операций CRUD. Как я уверен, вы, скорее всего, знаете, что Tomcat не обеспечивает управляемую контейнером персистентность, поэтому в моем компоненте CRUD-запроса я использую EnityManagerFactory, чтобы получить сворачивание менеджера enity. Теперь о допустимости моего выбора использовать bean-объект запроса в этой задаче, он, вероятно, открыт для обсуждения (снова), но я пытался поместить его в контекст того, что я прочитал в статьях, которые вы дали мне ссылки в частности, первый и второй. Из того, что я собираю, EclipseLink по умолчанию использует кэш 2-го уровня, в котором хранится кешированный объект. На примерах ExlipseLink - на сайте JPA Caching говорится, что:

Общий кэш существует на время единицы сохраняемости (EntityManagerFactory или сервер)

Теперь это не заставляет мои кэшированные сущности жить в течение доли времени во время вызова, который выполняется к бину запроса CRUD, потому что в тот момент, когда бин уничтожается и с ним EntityManagerFactory, то и кеш также. Также последняя часть вышеприведенного предложения «EntityManagerFactory, или server » вводит меня в заблуждение ... что именно подразумевается под или server в этом контексте и как его контролировать. Если я использую аннотацию @Cache и задаю соответствующее количество атрибута expire, выполнит ли это работу и сохранит ли сущности, хранящиеся в кэше L2 серверов, чем независимо от того, был ли мой EntityManagerFactory уничтожен?

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

Преимущества кэширования L2:

  • исключает доступ к базе данных для уже загруженных объектов
  • быстрее для чтения часто используемых неизмененных сущностей

Недостатками кэширования L2 являются:

  • потребление памяти для большого количества объектов
  • устаревшие данные для обновленных объектов
  • параллелизм для записи (исключение оптимистической блокировки или пессимистическая блокировка)
  • плохая масштабируемость для часто обновляемых или одновременно обновляемых объектов

Вам следует настроить кэширование L2 для объектов, которые:

  • читаю часто
  • изменяется редко
  • не критично, если устарел

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

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

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

  2. Сконфигурируйте аннотацию L2 @Cache для сущностей или, как в варианте 1 выше, создайте сессионный компонент с областью действия, который будет обрабатывать долгосрочное кэширование. Но разве они не возвращаются к моей первоначальной проблеме?

Мне бы очень хотелось услышать ваше мнение и посмотреть, что, по вашему мнению, может быть разумным способом подойти к этому, или, возможно, как вы подходили к нему в своих предыдущих проектах. О, и еще одна вещь, просто чтобы подтвердить ... при аннотировании сущности с помощью @Cache все связанные сущности будут кэшироваться вместе, поэтому мне не нужно аннотировать их все?

Снова все комментарии и указатели очень ценятся.


Спасибо за ваш ответ. Когда вы говорите

«В Tomcat лучше всего иметь статический менеджер, который будет удерживать EntityManagerFactory на время работы сервера».

Означает ли это, что я могу, например, объявить и инициализировать статическое поле EntityManagerFactory в области приложения, которая впоследствии будет использоваться всеми компонентами в течение всего жизненного цикла приложения?

1 Ответ

0 голосов
/ 30 августа 2011

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

Как правило, вы не хотите создавать новый EntityManagerFactory для запроса, только новый EntityManager. Создание нового EntityManagerFactory довольно дорого, поэтому не очень хорошая идея, даже игнорируя кэширование (у него есть собственный пул соединений, он должен инициализировать метаданные и т. Д.).

В Tomcat было бы лучше иметь некоторый статический менеджер, который удерживает EntityManagerFactory на время работы сервера. Либо никогда не закрывайте его, ни закрывайте, когда сервлет уничтожен.

...