L'implémentation d'un cache de second niveau (L2) est une stratégie essentielle pour réduire la charge sur la base de données dans les applications Spring Boot utilisant Hibernate. En utilisant Ehcache comme fournisseur de cache, les entités fréquemment consultées sont stockées en mémoire, évitant ainsi des allers-retours coûteux vers le disque.
Étape 1 : Gestion des dépendances Maven
Pour intégrer Ehcache 3 avec Hibernate 5+, vous devez inclure les bibliothèques JCache et l'implémetnation spécifique d'Ehcache dans votre fichier pom.xml.
<dependencies>
<!-- Persistance des données -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- Support JCache pour Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jcache</artifactId>
</dependency>
<!-- Moteur de cache Ehcache -->
<dependency>
<groupId>org.ehcache</groupId>
<artifactId>ehcache</artifactId>
<version>3.10.0</version>
</dependency>
</dependencies>
Étape 2 : Configuration de la couche JPA
La configuration s'effectue généralement dans le fichier application.yml. Ici, nous activons le cache de second niveau et spécifions la fabrique de régions Hibernate utilisant l'API JSR-107 (JCache).
spring:
jpa:
properties:
hibernate:
cache:
use_second_level_cache: true
use_query_cache: true
region:
factory_class: org.hibernate.cache.jcache.internal.JCacheRegionFactory
javax:
persistence:
sharedCache:
mode: ENABLE_SELECTIVE
generate_statistics: true
hibernate:
ddl-auto: update
Étape 3 : Paramétrage d'Ehcache
Créez un fichier nommé ehcache.xml dans le répertoire src/main/resources pour définir les politiques de rétention des données.
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://www.ehcache.org/v3"
xsi:schemaLocation="http://www.ehcache.org/v3 http://www.ehcache.org/schema/ehcache-core-3.0.xsd">
<cache-template name="base-config">
<expiry>
<ttl unit="seconds">3600</ttl>
</expiry>
<heap unit="entries">2000</heap>
</cache-template>
<cache alias="com.app.domain.InventoryItem" uses-template="base-config">
<heap unit="entries">500</heap>
</cache>
</config>
Le moteur utilise différentes stratégies d'éviction pour libérer de la place en mémoire :
- LRU (Least Recently Used) : Supprime les données dont l'accès est le plus ancien.
- LFU (Least Frequently Used) : Supprime les données les moins souvent sollicitées.
- FIFO (First In, First Out) : Supprime les données selon l'ordre chronologique d'insertion.
Étape 4 : Activation du cache sur les entités
Pour qu'une entité soit éligible au cache, utilisez l'annotation @Cache d'Hibernate ou l'annotation standard JPA @Cacheable.
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
import javax.persistence.Entity;
import javax.persistence.Id;
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class InventoryItem {
@Id
private Long sku;
private String label;
private Integer stockLevel;
// Getters et Setters
}
Étape 5 : Initialisation globale
Assurez-vous que la gestion du cache est activée au niveau de la classe principale de votre application Spring Boot.
@SpringBootApplication
@EnableCaching
public class InventoryServiceApplication {
public static void main(String[] args) {
SpringApplication.run(InventoryServiceApplication.class, args);
}
}
Analyse des paramètres avancés
Le contrôle fin du cache Hibernate repose sur plusieurs propriétés clés :
- hibernate.cache.use_query_cache : Permet de mettre en cache les résultats des requêtes HQL/JPQL en plus des entités individuelles.
- hibernate.cache.region_prefix : Utile dans les environnements multi-locataires pour isoler les espaces de cache.
- hibernate.cache.use_minimal_puts : Optimise les performences en évitant de mettre à jour le cache si la donnée n'a pas été modifiée.
- hibernate.generate_statistics : Crucial en phase de développement pour monitorer le taux de succès (hit rate) du cache.
- hibernate.cache.default_cache_concurrency_strategy : Définit la gestion des accès concurrents (ex:
NONSTRICT_READ_WRITEpour de meilleures performances sur des données peu sensibles).