Статьи

JPA Кэширование

JPA имеет 2 уровня кэширования. Первый уровень кэширования — это постоянный контекст.

Диспетчер сущностей JPA поддерживает набор управляемых сущностей в контексте постоянства.

Entity Manager гарантирует, что в пределах одного Постоянного контекста для любой конкретной строки базы данных будет только один экземпляр объекта. Однако этим же объектом можно управлять в транзакции другого пользователя, поэтому следует использовать либо оптимистическую, либо пессимистическую блокировку, как описано в JPA 2.0 Параллелизм и блокировка

Приведенный ниже код показывает, что поиск в управляемом объекте с тем же идентификатором и классом, что и у другого в том же контексте постоянства, вернет тот же экземпляр.

@Stateless public ShoppingCartBean implements ShoppingCart {

@PersistenceContext EntityManager entityManager;

public OrderLine createOrderLine(Product product,Order order) {
OrderLine orderLine = new OrderLine(order, product);
entityManager.persist(orderLine); //Managed
OrderLine orderLine2 =entityManager.find(OrderLine,
orderLine.getId()));
(orderLine == orderLine2) // TRUE
return (orderLine);
}

}

На диаграмме ниже показан жизненный цикл сущности по отношению к постоянному контексту.

Код ниже иллюстрирует жизненный цикл сущности. Ссылка на управляемый контейнером EntityManager внедряется с использованием аннотации контекста постоянства. Новый объект заказа создается, и объект имеет состояние нового. Persist называется, делая это управляемым объектом. Поскольку это сессионный компонент без сохранения состояния, он по умолчанию использует транзакции, управляемые контейнером, когда эта транзакция фиксируется, порядок в базе данных становится постоянным. Когда сущность строки заказа возвращается в конце транзакции, это отдельная сущность.

Контекст постоянства может быть либо с областью действия транзакции — контекст постоянства «живет» на протяжении транзакции, либо с расширенным — контекст постоянства охватывает несколько транзакций. С контекстом персистентности в пределах транзакции сущности «отключаются» в конце транзакции.

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

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

Приведенный ниже код показывает пример EJB сеанса с отслеживанием состояния с расширенным контекстом постоянства в сценарии варианта использования для добавления позиций в заказ. После сохранения порядка в методе createOrder он остается управляемым до тех пор, пока не будет вызван метод удаления EJB. В методе addLineItem объект заказа можно обновить, поскольку он управляется, и обновления будут сохранены в конце транзакции.

Приведенный ниже пример контрастирует с обновлением Порядка с использованием контекста персистентности в рамках транзакции и расширенного контекста персистентности. С контекстом персистентности в области транзакций необходимо выполнить поиск Entity Manager для поиска Заказа, который возвращает управляемый объект, который можно обновить. В расширенном контексте постоянства поиск не требуется. Преимущество в производительности, заключающееся в отсутствии чтения базы данных для поиска сущности, должно быть сопоставлено с недостатками использования памяти для кэширования и риском обновления кэшированных сущностей другой транзакцией. В зависимости от приложения и риска конфликта между одновременными транзакциями это может или не может дать лучшую производительность / масштабируемость.

JPA второго уровня (L2) кэширования

Кэширование JPA второго уровня (L2) разделяет состояние объекта в различных контекстах постоянства.

В JPA 1.0 не указана поддержка кэша второго уровня, однако большинство провайдеров персистентности предоставили поддержку кэша (ов) второго уровня. В JPA 2.0 указана поддержка основных операций кеширования с новым Cache API, который доступен из EntityManagerFactory, показанного ниже:

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

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

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

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

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

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

  • читаю часто
  • изменено нечасто
  • Не критично, если несвежий

Вы должны защитить любые данные, которые могут быть одновременно изменены с помощью стратегии блокировки:

  • Должен обрабатывать оптимистичные ошибки блокировки при сбросе / фиксации
  • настроить срок действия, обновить политику, чтобы минимизировать ошибки блокировки

Кэш запросов полезен для запросов, которые часто выполняются с одинаковыми параметрами, для неизмененных таблиц.

Архитектура кэширования поставщика сохраняемости EclipseLink JPA

Архитектура кэширования EclipseLink показана ниже.

Поддержка кеша второго уровня в EclipseLink включена по умолчанию, читаемые объекты кэшируются на уровне L2. Вы можете отключить кэш L2. EclipseLink кэширует объекты в L2, Hibernate кэширует идентификатор и состояние объектов в L2. Вы можете настроить кэширование по типу сущности или единице постоянства со следующими параметрами конфигурации:

  • Изоляция кэша, тип, размер, срок действия, координация, аннулирование, обновление
  • Координация (кластер-обмен сообщениями)
  • Обмен сообщениями: JMS, RMI, RMI-IIOP,…
  • Режим: SYNC, SYNC + NEW, INVALIDATE, NONE

В приведенном ниже примере показано, как настроить кэш L2 для объекта с помощью аннотации @Cache.

Архитектура кэширования провайдера Hibernate JPA

Архитектура кэширования провайдера Hibernate JPA отличается от EclipseLink: она не настроена по умолчанию, она не кэширует объекты, а только id и состояние, и вы можете подключать разные кэши L2. На приведенной ниже схеме показаны различные типы кэша L2, которые вы можете подключить к Hibernate.

Конфигурация кэша зависит от типа подключенного кэширования. В приведенном ниже примере показано, как настроить кэш L2 в спящем режиме для объекта с помощью аннотации @Cache.

За дополнительной информацией:

Представляем EclipseLink

EclipseLink JPA Руководство пользователя

Кэширование второго уровня в Hibernate Ускорьте

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

Hibernate

Java Persistence API 2.0: что нового

Начало платформы Java ™ EE 6 с GlassFish ™ 3

Pro EJB 3: API персистентности Java (JPA 1.0)