Implémenter un cache secondaire de Hibernate avec NCache

Dans ce tutoriel, nous explorerons la mise en œuvre d’une cache de second niveau dans Hibernate en utilisant NCache.

Nous allons configurer une application Java avec Hibernate. Ensuite, nous configurons NCache en tant que cache de second niveau. Finalement, nous testerons l’implémentation pour voir comment le cache réduit la charge de la base de données et améliore les performances.

Les bases

Avant de plonger dans l’implémentation, laissez-nous aborder les bases de Hibernate, de NCache et du cache de second niveau de Hibernate.

Hibernate

Hibernate est une plateforme open source de mapping objet-relationnel (ORM) pour les applications Java. Elle simplifie la programmation des interactions avec la base de données en mappant les objets Java aux tables de base de données et l’inverse.

Pour améliorer les performances, Hibernate propose deux niveaux de cache :

1. Cache de Premier Niveau

Le cache de premier niveau est associé à la session Hibernate et est activé par défaut. Il stocke les objets récupérés pendant une session et élimine la nécessité de vérifier la base de données plusieurs fois pour le même objet.

Le cache de premier niveau est limité à la portée d’une session et n’est pas partagé entre sessions.

Il n’est également pas persistant et est vidé lorsque la session est fermée ou explicitement nettoyée.

2. Cache de Deuxième Niveau

La seconde mémoire cache est partagée entre les sessions et peut être configurée pour stocker les données au niveau de l’application. Elle réduit le nombre d’appels à la base de données en conservant les objets plus longtemps.

La mémoire cache de niveau 2 doit être configurée explicitement et peut être mise en œuvre à l’aide de divers fournisseurs de cache comme NCache, Ehcache, etc.

NCache

NCache est une solution de cache distribué pour les applications .NET et Java. Il fournit un stockage de données en mémoire qui peut être utilisé pour stocker les données fréquemment accédées et améliorer les performances de l’application.

NCache supporte diverses topologies de cache telles que répliquées, partitionnées et client.

NCache peut être utilisé comme cache de niveau 2 dans Hibernate pour stocker et récupérer des objets du cache plutôt que d’effectuer des appels à la base de données.

Code Setup

Commençons par créer une application Java et configurer Hibernate pour interagir avec la base de données.

Nous utilisons Maven pour gérer les dépendances et construire le projet. L’application aura une classe d’entité pour définir les données et une classe cliente pour interagir avec la base de données.

Tout d’abord, nous allons tester l’application sans cache pour voir les interactions avec la base de données. Ensuite, nous configurons NCache comme cache de niveau 2 dans Hibernate pour cacher les objets d’entité et réduire les appels à la base de données.

Dépendances

Nous commençons par ajouter les dépendances requises pour Hibernate et NCache dans le fichier 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>

Veuillez noter que les versions mentionnées ici peuvent varier en fonction des dernières sorties. Assurez-vous d’utiliser les versions appropriées pour votre projet.

Classe Entité

Maintenant, créez une classe entité pour représenter les données que vous souhaitez mettre en cache. Nous définirons une simple classe Client avec des champs id et name :

@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 }

La classe Client est annotée avec @Entity et @Cacheable pour la définir comme une entité pouvant être mise en cache. Elle a un champ id annoté avec @Id et @GeneratedValue pour générer des identifiants uniques automatiquement.

Nous utilisons également l’annotation @Cache pour spécifier la stratégie de cache et la région pour l’entité.

NONSTRICT_READ_WRITE indique à Hibernate de mettre à jour le cache lorsque des données sont lues ou écrites avec une cohérence eventuelle.

L’attribut region spécifie la région de cache où les données seront stockées.

Nous configurons NCache pour utiliser cette région pour stocker les données en cache.

Configuration de Hibernate

Nous devons configurer Hibernate pour interagir avec la base de données et activer le cache.

Créons un fichier hibernate.cfg.xml dans le répertoire src/main/resources avec la configuration suivante :

<?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>

Dans ce fichier de configuration, nous spécifions les détails de la connexion à la base de données, le dialecte et les réglages de cache. Nous utilisons Oracle comme base de données et configurons Hibernate pour mettre à jour le schéma automatiquement.

Classe Client

Nous allons créer une classe de client pour interagir avec la base de données et tester le mécanisme de mise en cache. Nous pouvons écrire une classe main pour sauver et récupérer des objets Customer à l’aide de 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(); } }

Dans cette classe de client, nous créons une SessionFactory en utilisant la configuration de Hibernate et ouvrir une session pour interagir avec la base de données. Nous sauvegardons un objet Customer dans la base de données et l’extraisons en utilisant l’id.

Ensuite, nous appelons la méthode retrieveCustomer deux fois dans deux sessions distinctes pour observer les interactions avec la base de données sans le cache.

Nous constatons que la base de données est sollicitée deux fois pour récupérer le même objet :

Comme nous pouvons le voir, la requête de Hibernate est exécutée deux fois.

Configuration du serveur NCache

Pour utiliser NCache comme cache secondaire dans Hibernate, nous devons configurer un serveur NCache et l’initialiser pour stocker les données en cache.

NCache fournit une solution de cache distribué qui peut être installée sur des serveurs Windows et Linux. Nous allons créer un cluster de cache en utilisant NCache et le configurer. Une fois que le cluster de cache est mis en place, nous pouvons nous connecter à celui-ci depuis notre application Java.

Activation du cache secondaire NCache dans Hibernate

Une fois le serveur NCache configuré, nous pouvons configurer Hibernate pour utiliser NCache comme fournisseur de cache secondaire. Nous mettrons à jour le fichier de configuration de Hibernate et spécifierons les réglages de cache pour activer le cache.

Activation des régions de cache

Mettez-en place les paramètres de cache dans le fichier hibernate.cfg.xml pour activer NCache en tant que fournisseur de cache de deuxième niveau :

<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>

Dans cet exemple, nous définissons la propriété hibernate.cache.use_second_level_cache à true pour activer le cache de deuxième niveau. Nous spécifions également la propriété hibernate.cache.region.factory_class pour utiliser la classe NCacheRegionFactory, une implémentation de JCacheRegionFactory, en tant que fournisseur de cache.

Configurer les propriétés NCache

NCache fournit une série de propriétés pour configurer les réglages de cache dans Hibernate. Nous pouvons les définir dans le fichier 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>

Dans ce fichier de configuration, nous définissons la région de cache CustomerRegion avec le nom du cache, la priorité, le type d’expiration et la période d’expiration. Nous définissons le expiration-type à Sliding avec une période d’expiration de 8 secondes. Cela signifie que les données en cache expirent après 8 secondes d’inactivité et sont retirées du cache.

De plus, nous définissons une DefaultRegion avec des réglages par défaut pour d’autres entités qui n’ont pas de région de cache spécifique. Cela sert de région de secours pour les entités qui ne sont pas explicitement configurées.

Avec plusieurs régions de cache, nous pouvons définir différents réglages de cache pour différentes entités en fonction de leurs exigences.

D’abord, nous définissons une dépendance de base de données pour l’entité Customers. Cela permet de maintenir la cache en sync avec la base de données et de mettre à jour/supprimer les données de cache lorsque des modifications sont effectuées dans la base de données.

Nous spécifions l’énoncé SQL pour récupérer le CustomerID à partir de la table Customers et la chaîne de connexion pour se connecter à la base de données.

Le format de clé de cache spécifie comment la clé de cache est générée en fonction de la clé primaire de l’entité.

Test

Maintenant que nous avons configuré NCache comme cache de second niveau dans Hibernate, essayons de tester l’application pour voir comment le cache améliore les performances. Nous lancons à nouveau la classe cliente et observons les interactions avec la base de données avec le cache activé.

Lorsque nous lançons la classe cliente, nous verrons que la première appel pour récupérer l’objet Customer atteint la base de données pour récupérer les données. Cependant, la deuxième appel pour récupérer le même objet le récupérera à partir du cache plutôt que de refaire à nouveau l’appel à la base de données. Cela démontre comment le cache réduit la charge de la base de données et améliore les performances en servant les données depuis le cache.

Avantages de l’utilisation de NCache avec Hibernate

L’utilisation de NCache comme cache de second niveau dans Hibernate offre plusieurs avantages :

  • Amélioration des performances : NCache offre un stockage en mémoire rapide pour les données en cache, réduisant la latence et améliorant la throughput. Il fournit également des opérations asynchrones pour mettre à jour le cache en arrière-plan, réduisant ainsi l’impact sur les performances de l’application.
  • Scalabilité : Au fur et à mesure que l’application se développe, NCache peut se scaler horizontalement pour gérer de grandes quantités de données et de requêtes utilisateur. Il peut être déployé dans un cluster et supporte des fonctionnalités telles que la réplication du cache et la partitionnement pour distribuer la charge.
  • Flexibilité : NCache offre diverses topologies de cache et configurations pour répondre à différentes exigences d’applications. De plus, à cause de l’utilisation de régions de cache, différentes entités peuvent avoir différentes configurations de cache en fonction de leurs besoins. Cela permet un contrôle fin des comportements de cache.
  • Synchronisation : NCache offre la possibilité de synchroniser la base de données pour maintenir le cache en sync avec la base de données. Cela garantit que les données en cache sont à jour et reflètent les dernières modifications effectuées dans la base de données.

Résumé

Dans ce tutoriel, nous avons exploré la mise en œuvre d’un cache de niveau 2 dans Hibernate en utilisant NCache pour les applications Java.

Nous avons commencé par comprendre les bases de Hibernate, NCache et le cache de niveau 2 de Hibernate. Ensuite, nous avons configuré une application Java avec Hibernate et configuré NCache comme cache de niveau 2. Enfin, nous avons testé l’implémentation pour voir comment le cache améliore les performances en réduisant les appels à la base de données et en servant les données depuis le cache.

En utilisant NCache avec Hibernate, les développeurs peuvent améliorer les performances, la scalabilité et la fiabilité de leurs applications en exploitant la puissance du cache distribué. NCache offre une solution de cache robuste qui intègre parfaitement avec Hibernate et d’autres frameworks Java, ce qui en fait un choix idéal pour le cache des données dans les applications Java.

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