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

Кэщ сущностей

Кэш сущностей предоставляется фреймворком EclipseLink ORM. Он сохраняет недавно прочитанные или записанные экземпляры сущностей в памяти, что сводит к минимуму необходимость доступа к базе данных и повышает производительность приложения.

Кэш сущностей используется только при извлечении по ID, поэтому запросы по другим атрибутам по-прежнему выполняются к базе данных. Однако эти запросы могут быть проще и быстрее, если связанные сущности кэшированы. Например, если вы запрашиваете несколько заказов Orders вместе со связанными клиентами Customers и не используете кэш, SQL-запрос будет содержать JOIN для таблицы Customers. Если сущности Customer кэшированы, SQL-запрос выберет только Orders, и связанные Customers будут извлечены из кэша.

Чтобы включить кэширование для сущности, установите свойства приложения eclipselink.cache.shared.<entity_name> и eclipselink.cache.size.<entity_name>. В приведенном ниже примере для сущности User установлен кэш с максимальным размером в 500 экземпляров:

eclipselink.cache.shared.User = true
eclipselink.cache.size.User = 500

По умолчанию имя сущности – простое имя класса.

Но имя также можно задать явно в аннотации @Entity(name = "<entity_name>").

Размер кэша для сущности по умолчанию равен 100 экземплярам.

При использовании фетч-планов факт кэширования сущности влияет на режим извлечения, выбираемый фреймворком для загрузки ссылок. Если ссылочный атрибут является кэшируемой сущностью, режим извлечения всегда устанавливается в UNDEFINED. Это позволяет ORM извлекать ссылку из кэша вместо выполнения запросов с JOIN или отдельных пакетных запросов.

При работе в распределенной конфигурации Jmix обеспечивает синхронизацию кэша сущностей между узлами кластера.

Кэш запросов

Кэш запросов хранит идентификаторы экземпляров сущностей, возвращаемых JPQL-запросами, поэтому он естественным образом дополняет кэш сущностей.

Например, если кэш включен для сущности (скажем, Customer), и вы впервые выполняете запрос select c from Customer c where c.grade = :grade, происходит следующее:

  • ORM запускает запрос к базе данных.

  • Загруженные экземпляры Customer помещаются в кэш сущностей.

  • Сопоставление текста запроса и параметров со списком ID возвращаемых экземпляров помещается в кэш запросов.

При выполнении того же запроса с теми же параметрами во второй раз, фреймворк находит запрос в кэше запросов и загружает экземпляры сущностей из кэша сущностей по ID. С базой данных никаких операций не выполняется.

По умолчанию запросы не кэшируются. Указать, что запрос должен кэшироваться можно на разных уровнях приложения:

  • Используя XML-атрибут cacheable = "true" или метод setCacheable(true) интерфейса CollectionLoader при работе с загрузчиками данных.

  • Используя метод cacheable(true) интерфейса fluent loader при работе с DataManager.

  • Используя метод setCacheable(true) интерфейса Query при работе с EntityManager.

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

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

Бин JMX jmix.eclipselink:type=QueryCache можно использовать для мониторинга состояния кэша и удаления кэшированных запросов вручную. Например, если вы изменили экземпляр сущности Customer непосредственно в БД, то необходимо удалить все кэшированные запросы для этой сущности, используя операцию evict(), предоставляющую Customer в качестве аргумента.

Если вы хотите отключить кэш запросов для всех сущностей независимо от вызовов API, описанных выше, установите для свойства приложения jmix.eclipselink.query-cache-enabled значение false. По умолчанию указано true.