web-dev-qa-db-fra.com

Spring Boot 2.0 Hibernate 5 Ehcache 3 avec JCache

J'essaie de configurer l'hibernation avec Ehcache comme le cache de deuxième niveau, mais le TTL ne fonctionne pas.

Voici mes dépendances:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-cache</artifactId>
</dependency>

<dependency>
  <groupId>org.hibernate</groupId>
  <artifactId>hibernate-jcache</artifactId>
</dependency>

<dependency>
  <groupId>org.ehcache</groupId>
  <artifactId>ehcache</artifactId>
</dependency>

<dependency>
  <groupId>javax.cache</groupId>
  <artifactId>cache-api</artifactId>
</dependency>

Voici ma configuration YAML:

spring:
  jpa:
    show-sql: true
    properties:
      hibernate:
        dialect: Dialect
        cache:
          use_second_level_cache: true
          region.factory_class: org.hibernate.cache.jcache.JCacheRegionFactory
          use_query_cache: true
  cache:
    jcache:
      config: classpath:ehcache.xml

Voici comment ma classe d'entité est configurée:

@Entity
@javax.persistence.Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class PersonEntity {
  //
}

Et le jParepository pour l'entité:

public interface PersonRepository extends JpaRepository<PersonEntity, Integer> {
  @org.springframework.data.jpa.repository.QueryHints({
      @javax.persistence.QueryHint(name = "org.hibernate.cacheable", value = "true")
  })
  List<PersonEntity> findByName(String name);
}

J'ai configuré le cache pour expirer dans 2 secondes, mais appeler findByName _ utilise toujours le cache (il n'y a pas de requêtes SQL imprimées après la première).

Ici se trouve le ehcache.xml déposer:

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns="http://www.ehcache.org/v3">

  <cache-template name="simple">
    <expiry>
      <ttl>2</ttl>
    </expiry>
    <heap>100</heap>
  </cache-template>

  <cache alias="com.sample.PersonEntity" uses-template="simple"/>

</config>

Edit: J'ai fait du débogage. J'ai ajouté un point de pause dans org.ehcache.jsr107.ExpiryPolicyToEhcacheExpiry:

javax.cache.expiry.Duration duration = this.expiryPolicy.getExpiryForCreation();

Cette durée est infinie pour une raison quelconque. Alors peut-être que la configuration n'est pas définie correctement? Je sais que le XML est en train d'être lu parce que lorsque je l'invalide (en supprimant la balise de tas par exemple), je reçois une erreur.

enter image description here

6
George

Quand vous définissez votre @Cacheable Annotation sur votre entité Il crée une région où le KEY est le ID de l'entité et le Value est l'entité. Ce qui précède signifie que vous allez frapper le cache si vous accédez par clé qui est le ID. Si vous utilisez des données de printemps et de la FindbyID, il frappera le cache. Si vous créez une méthode FindbyName, l'accès ne sera pas à l'aide de la clé, il ne frappera pas la région de cache définie par votre Cacheable annotation. D'autre part, il frappera le cache de requête, mais le cache de requête est dans une région entièrement différente. Et juger de votre configuration Vous n'avez pas configuré le cache de requête à l'ensemble .Pour cette méthode pour toucher n'importe quel cache, vous devez l'ajouter à l'aide de cette propriété:

spring:jpa:properties:hibernate:cache:use_query_cache: true

Alternativement, vous pouvez spécifier @cacheable en haut de la méthode du référentiel de cette manière définir une nouvelle région.

Vous pouvez configurer le cache par défaut, cela devrait capter la StandardQuiseryCahache.

<defaultCache 
    maxElementsInMemory="10000"
    eternal="false"
    timeToIdleSeconds="3600"
    timeToLiveSeconds="3600">
  </defaultCache>

Dans eHCache2, vous pouvez configurer le cache de requête standard via cet élément:

  <cache
name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600">

Je ne sais pas comment il est dans ehcache 3 cependant. Je crois que cela devrait être le même, car la classe StandartqueryCache fait partie du forfait Hibernate et ne fait pas partie du paquet EHCache.

Je pense aussi que vous avez besoin de définir
[.____] hibernate.javax.cache.provider = org.ehcache.jsr107.ehcachecachingProvider

0
Alexander Petrov