Implement Hibernate Second-Level Cache With NCache

В этом руководстве мы посмотрим, как в Hibernate с помощью NCache реализовать второе уровне кэширования.

Мы настроим Java-приложение с Hibernate, затем настроим NCache как второе уровне кэширования. В конце мы проверим реализацию, чтобы посмотреть, как кэширование уменьшает нагрузку на базу данных и улучшает производительность.

Основы

До того, как мы перейдем к реализации, посмотрим на основы Hibernate, NCache и второго уровня кэширования Hibernate.

Hibernate

Hibernate — открытая системаマッピング Java объектов на таблицы базы данных (ORM-фреймворк) для приложений на Java. Она упрощает разработку взаимодействий с базой данных, マッピруя Java объекты к таблицам базы данных и наоборот.

Чтобы улучшить производительность, Hibernate обеспечивает два уровня кэширования:

1. Первый уровень кэширования

Первый уровень кэширования связан с сессией Hibernate и включен по умолчанию. Он хранит объекты, извлеченные во время сессии, и устраняет необходимость Many times hitting the database for the same object.

Первый уровень кэширования ограничен сроком действия сессии и не sharable across sessions.

Он также не persistent и очищается, когда сессия закрывается или очищается явно.

2. Второй уровень кэширования

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

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

NCache

NCache — это распределенное решение для кэширования для .NET и Java приложений. Он предоставляет хранилище данных в памяти, которое можно использовать для кэширования часто запрашиваемых данных и улучшения производительности приложения.

NCache поддерживает различные топологии кэширования, такие как реплицированные, партиционированные и клиентский кэш.

NCache можно использовать в качестве вторичного кэша в Hibernate для хранения и извлечения объектов из кэша вместо обращения к базе данных.

Настройка кода

Начнем с создания Java приложения и настройки Hibernate для взаимодействия с базой данных.

Мы будем использовать Maven для управления зависимостями и сборки проекта. Приложение будет иметь класс сущности для определения данных и класс клиента для взаимодействия с базой данных.

Сначала мы протестируем приложение без кэширования, чтобы увидеть взаимодействия с базой данных. Затем мы настроим NCache в качестве вторичного кэша в Hibernate для кэширования объектов сущностей и уменьшения обращений к базе данных.

Зависимости

Начнем с добавления необходимых зависимостей для Hibernate и NCache в файл pom.xml:

<dependencies> <!-- Hibernate dependencies --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>6.6.1.Final</version> </dependency> <!-- NCache dependencies --> <dependency> <groupId>com.alachisoft.ncache</groupId> <artifactId>ncache-hibernate</artifactId> <version>5.3.3</version> </dependency> </dependencies>

Note that the versions mentioned here may vary based on the latest releases. Make sure to use the appropriate versions for your project.

Класс сущности

Теперь создадим класс сущности для представления данных, которые мы хотим кэшировать. Define a simple Customer class with id and name fields:

@Entity @Cacheable @org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE, region = "CustomerRegion") public class Customer { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; // getters and setters }

The Customer class is annotated with @Entity and @Cacheable to define it as a cacheable entity. It has an id field annotated with @Id and @GeneratedValue to generate unique identifiers automatically.

We also use the @Cache annotation to specify the caching strategy and region for the entity.

NONSTRICT_READ_WRITE tells Hibernate to update the cache when data is read or written with eventual consistency.

The region attribute specifies the cache region where the data will be stored.

We’ll configure NCache to use this region to store the cached data.

Hibernate Configuration

We need to configure Hibernate to interact with the database and enable caching.

Let’s create a hibernate.cfg.xml file in the src/main/resources directory with the following configuration:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property> <property name="hibernate.connection.url">jdbc:oracle:thin:@localhost:1521:xe</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password">password</property> <property name="hibernate.dialect">org.hibernate.dialect.Oracle12cDialect</property> <property name="hibernate.hbm2ddl.auto">update</property> <property name="hibernate.show_sql">true</property> </session-factory> </hibernate-configuration>

In this configuration file, we specify the database connection details, dialect, and cache settings. We use Oracle as the database and configure Hibernate to update the schema automatically.

Клиентский класс

Мы создаем класс клиента для взаимодействия с базой данных и тестирования механизма кэширования. Мы можем написать класс main, чтобы сохранять и извлекать объекты Customer с использованием Hibernate:

public class HibernateClient { public static void main(String[] args) { SessionFactory sessionFactory = new Configuration().configure().buildSessionFactory(); Session session = sessionFactory.openSession(); Transaction transaction = session.beginTransaction(); Customer customer = new Customer(); customer.setName("John Doe"); session.save(customer); transaction.commit(); session.close(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); Customer retrievedCustomer = session.get(Customer.class, customer.getId()); System.out.println("Retrieved Customer: " + retrievedCustomer.getName()); transaction.commit(); session.close(); session = sessionFactory.openSession(); transaction = session.beginTransaction(); retrievedCustomer = session.get(Customer.class, customer.getId()); System.out.println("Retrieved Customer: " + retrievedCustomer.getName()); transaction.commit(); session.close(); } }

В этом клиентском классе мы создаем SessionFactory с помощью Hibernate-конфигурации и открываем сессию для взаимодействия с базой данных. Мы сохраняем объект Customer в базу данных и извлекаем его с помощью id.

Потом мы вызываем метод retrieveCustomer дважды в двух разных сессиях, чтобы проверить взаимодействия с базой данных без кэширования.

Мы увидим, что база данных дважды вызывается для извлечения одного и того же объекта:

Как видим, Hibernate-запрос выполняется дважды.

Настройка сервера NCache

Чтобы использовать NCache в качестве второго уровня кэширования в Hibernate,我们需要 настроить сервер NCache и настроить его для хранения кэшированных данных.

NCache предоставляет решение для распределенного кэширования, которое может быть установлено на серверах Windows и Linux. Мы создадим кэш- кластер с использованием NCache и настроим его. once the cache cluster is set up, мы можем подключиться к нему из нашей Java-приложения.

Включение NCache в качестве Второго Уровня Кэша в Hibernate

once the NCache server is set up, мы можем настроить Hibernate, чтобы использовать NCache в качестве провайдера второго уровня кэширования. Мы обновим файл конфигурации Hibernate и определим настройки кэш-регионов для включения кэширования.

Включение регионов кэша

Для обновления настроек кэша в файле hibernate.cfg.xml и позволения использовать NCache в качестве второго уровня кэша мы будем делать следующее:

<hibernate-configuration> <session-factory> <property name="hibernate.cache.use_second_level_cache">true</property> <property name="hibernate.cache.region.factory_class">com.alachisoft.ncache.NCacheRegionFactory</property> ... </session-factory> </hibernate-configuration>

В этом месте мы устанавливаем свойство hibernate.cache.use_second_level_cache на true, чтобы включить второй уровень кэша. Также мы указываем свойство hibernate.cache.region.factory_class, чтобы использовать NCacheRegionFactory, реализацию JCacheRegionFactory, в качестве провайдера кэша.

Конфигурирование свойств NCache

NCache обеспечивает набор свойств для настройки параметров кэша в Hibernate. Эти настройки можно задать в файле ncache-hibernate.xml:

<configuration> <application-config application-id="myapp" enable-cache-exception="true" default-region-name="DefaultRegion" key-case-sensitivity="false"> <cache-regions> <region name="CustomerRegion" cache-name="demoCache" priority="AboveNormal" expiration-type="Sliding" expiration-period="8"/> <region name="DefaultRegion" cache-name="demoCache" priority="default" expiration-type="None" expiration-period="0"/> </cache-regions> <database-dependencies> <dependency entity-name="hibernator.BLL.Customer" type="oledb" sql-statement="SELECT CustomerID FROM Customers WHERE CustomerID ='?';" cache-key-format="Customers#[pk]" connection-string="Provider=SQLOLEDB;Data Source=20.200.20.40,1433;Initial Catalog=Northwind;User ID=john;Password=1234;"/> </database-dependencies> </application-config> </configuration>

В этом конфигурационном файле мы определяем регион кэша CustomerRegion с именем кэша, приоритетом, типом исчезновения и периодом исчезновения. Мы устанавливаем expiration-type на Sliding с периодом исчезновения в 8 секунд. Это означает, что данные, кэшированные в регионе, истекут после 8 секунд неактивности и будут удалены из кэша.

Кроме того, мы определяем регион DefaultRegion с Default настройками для других сущностей, которые не имеют специального региона кэша. Это используется в качествеallback региона для сущностей, которые не конфигурированы явно.

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

Далее мы определяем зависимость базы данных для сущности Customers. Это используется для синхронизации кэша с базой данных и обновления/удаления кэшированных данных, когда происходит изменение в базе данных.

Мы указываем SQL-запрос для извлечения CustomerID из таблицы Customers и строку соединения для подключения к базе данных.

Формат ключа кэша определяет, как генерируется ключ кэша на основе первичного ключа сущности.

Тестирование

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

Когда мы запускаем клиентский класс, мы увидим, что первый вызов для извлечения объекта Customer заставляет пройти к базе данных, чтобы получить данные. Однако второй вызов для извлечения того же объекта будет забирать его из кэша, вместо того, чтобы снова зайти в базу данных. Это демонстрирует, как кэширование уменьшает нагрузку на базу данных и улучшает производительность, выдавая данные из кэша.

Польза от использования NCache с Hibernate

Использование NCache в качестве второго уровня кэша в Hibernate обеспечивает ряд преимуществ:

  • Улучшенная производительность: NCache обеспечивает быстрое встроенное хранение данных в кеше, что помогает снизить задержки и улучшить пропускную способность. Также он поддерживает асинхронные операции для обновления кеша в фоновом режиме, что помогает снизить влияние на производительность приложения.
  • Скалярность: При росте приложения NCache может работать в режиме горизонтального масштабирования, чтобы обрабатывать большие объемы данных и запросы пользователей. Он может быть развернут в кластере и поддерживает такие функции, как репликация кеша и распределение нагрузки.
  • Свободность: NCache обеспечивает различные модели кеширования и настройки для соответствия различным требованиям приложений. Более того, благодаря использованию регионов кеша, различные сущности могут иметь различные настройки кеша в соответствии с их потребностями. Это позволяет мелкому управлению поведением кеширования.
  • Синхронизация: NCache提供了数据库同步选项,以保持缓存与数据库的同步。这确保了缓存中的数据是最新的,并反映了数据库中最新的更改。

Резюме

В этой статье мы исследовали внедрение второго уровня кеширования в Hibernate с использованием NCache для Java-приложений.

我们首先理解了Hibernate、NCache和Hibernate第二级缓存的基本知识。然后,我们在Java应用程序中设置了Hibernate,并配置了NCache作为第二级缓存。最后,我们测试了实现,以查看缓存如何通过减少数据库查询和从缓存中提供数据来提高性能。

При использовании NCache с Hibernate разработчики могут повысить производительность, скорость масштабирования и надежность своих приложений, используя возможности распределенного кэширования. NCache предлагает надежную решение кэширования, которое гармонично интегрируется с Hibernate и другими Java-фреймворками, делая его идеальным выбором для кэширования данных в Java-приложениях.

Source:
https://dzone.com/articles/implement-hibernate-second-level-cache-with-ncache