Кэширование объектов JPA2

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

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

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

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

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

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

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

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

Вы должны настроить кэширование L2 для сущностей, которые:

  • читать часто
  • модифицируется нечасто
  • не критично если несвежий

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

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

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

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

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

Опять же, все комментарии и указатели высоко ценятся.


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

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

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


person fissk    schedule 26.08.2011    source источник


Ответы (1)


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

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

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

person James    schedule 30.08.2011