wake-up-neo.net

Spring Boot + JPA2 + Hibernate - Aktivieren Sie den Second-Level-Cache

Ich verwende Spring Boot 1.2.5 mit JPA2, um Entitäten mit Anmerkungen zu versehen (und als unterliegende JPA-Implementierung den Ruhezustand zu aktivieren).

Ich wollte Second-Level-Cache in diesem Setup verwenden, daher wurden Entitäten mit @javax.persistence.Cacheable versehen.

Ich habe auch folgendes in application.properties hinzugefügt:

spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory

Während des Boot-Ups beklagte sich der Winterschlaf über das Fehlen von EhCacheRegionFactory, also fügte ich dies zu pom hinzu:

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

Abfragen wie entityManager.find(Clazz.class, pk) lösen jedoch immer noch DB-Abfragen aus, anstatt zwischengespeicherte Daten zu verwenden.

Irgendeine Idee, was fehlt?

16
Daimon

Nun, nach etwas mehr Graben hier, was mir in application.properties fehlte:

spring.jpa.properties.javax.persistence.sharedCache.mode=ALL

Hoffe es hilft jemandem :)

26
Daimon

@Daimon Ich bin mir nicht wirklich sicher, ob

spring.jpa.properties.javax.persistence.sharedCache.mode=ALL

ist die beste entscheidung.

Zitiert aus Hibernate 20.2.1. Abschnitt zur Dokumentation der Cache-Zuordnungen

Standardmäßig sind Entitäten nicht Teil des Caches der zweiten Ebene. Wir empfehlen, dass Sie sich an diese Einstellung halten. Sie können dies jedoch überschreiben, indem Sie das Element shared-cache-mode in Ihrer Datei persistence.xml festlegen oder die Eigenschaft javax.persistence.sharedCache.mode in Ihrer Konfiguration verwenden.

wohingegen

ENABLE_SELECTIVE (Standardwert und empfohlener Wert): Entitäten werden nicht zwischengespeichert, es sei denn, sie sind ausdrücklich als zwischenspeicherbar markiert.

Könnte es also sein, dass Sie nicht alle betroffenen Entitäten mit @ javax.persistence.Cacheable oder @ org.hibernate.annotations.Cache kommentiert haben? Dies kann dazu führen, dass der Abfrage-Cache versucht hat, die betroffenen Entitäten im Second Level-Cache ohne Erfolg zu suchen, und dann mit einem einzigen Auswahlvorgang begonnen hat, jede Entität abzurufen.

7
GeBeater

Hast du hinzugefügt 

@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 

auf der Klasse, die Sie zwischenspeichern möchten?

2
m1416

Sie sollten eine ehcache.xml-Datei in Ihrem Klassenpfad haben. Die Datei sollte mindestens die Standardcachestrategie enthalten. Um das Debuggen zu vereinfachen, stellen Sie sicher, dass die Entitäten nicht aus dem Cache entfernt werden: 

ehcache.xml:

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xsi:noNamespaceSchemaLocation="ehcache.xsd"
  Name="CacheManager" 
  maxBytesLocalHeap="250m">

<defaultCache eternal="true"
...
/>

<cache name="org.hibernate.cache.internal.StandardQueryCache"
       eternal="true"
...
/>

Um sicherzustellen, dass alles in Ordnung ist, sollten Sie beim Start der Anwendung das folgende Protokoll haben:

Could not find a specific ehcache configuration for cache named [com.yourcompany.YourClass]; Using defaults.

Das bedeutet, dass Ihre Entity-Cache-Anmerkung korrekt gelesen wurde und der Standardcache verwendet wird.

Wenn Sie mit entityManager.find(Clazz.class, pk) testen, ist dies nicht der Abfrage-Cache, sondern nur der Entitäts-Cache. Der Abfragecache wird für Abfragen (em.createQuery (...) und für Beziehungen verwendet

Ich benutze auch org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory, weiß aber nicht, was besser ist.

0
crv

Sie können einen Drittanbieter-Cacheanbieter verwenden, darunter JCache, Ehcache, Gvava Cache, Hazelcast Cache und Caffeine Cache.

Bitte lesen Sie diese Antwort unter Quora , um zu erfahren, wie Sie den Second-Level-Cache in Spring Boot aktivieren und konfigurieren.

0
Arun Raaj

Um alles zusammenzufassen (L2-Cache und Abfrage-Cache):

Als Erstes müssen Sie den Cache-Provider (ich empfehle die Verwendung von EhCache) zu Ihrem Klassenpfad hinzufügen.

In der vorherigen Version von Hibernate (vor 5.3) wird dies durch Hinzufügen dieser Abhängigkeit erreicht. Diese Abhängigkeit enthält EhCache 2, der jetzt eingestellt wird.

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-ehcache</artifactId>
    <version>your_hibernate_version</version>
</dependency>

In neueren Versionen von Hibernate-Caches sollte die JSR-107-API (JCache) verwendet werden. Es werden also zwei Abhängigkeiten benötigt - eine für die JSR-107-API und die zweite für die eigentliche JCache-Implementierung (EhCache 3).

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

<dependency>
    <groupId>org.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>3.6.3</version>
    <scope>runtime</scope>
</dependency>

Nun geht es weiter zur Datei application.properties/yml:

spring:
  jpa:
    #optional - show SQL statements in console. 
    show-sql: true 
    properties:
      javax:
        persistence:
          sharedCache: 
            #required - enable selective caching mode - only entities using @Cacheable annotation will use L2 cache.
            mode: ENABLE_SELECTIVE 
      hibernate:
        #optional - enable SQL statements formatting.
        format_sql: true 
        #optional - generate statistics to check if L2/query cache is actually being used.
        generate_statistics: true
        cache:
          #required - turn on L2 cache.
          use_second_level_cache: true
          #optional - turn on query cache.
          use_query_cache: true 
          region:
            #required - classpath to cache region factory.
            factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory 

Für EhCache 3 sollte diese Region verwendet werden:

factory_class: org.hibernate.cache.jcache.JCacheRegionFactory

Sie können auch die Protokollierung der TRACE-Ebene für Hibernate aktivieren, um Ihren Code zu überprüfen:

logging:
  level:
    org:
      hibernate:
        type: trace

Nun zum Code. Um das L2-Caching für Ihre Entität zu aktivieren, müssen Sie die beiden Anmerkungen hinzufügen:

@javax.persistence.Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE) //Provide cache strategy.
public class MyEntity {
  ...
}

Note - wenn Sie Ihre @OneToMany- oder @ManyToOne-Relation zwischenspeichern möchten - fügen Sie @Cache-Anmerkung auch über dieses Feld hinzu.

Und um den Abfrage-Cache in Ihrem Spring-Data-JPA-Repository zu aktivieren, müssen Sie die richtige Variable QueryHint hinzufügen.

public class MyEntityRepository implements JpaRepository<MyEntity, Long> {

  @QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true"))
  List<MyEntity> findBySomething(String something);

}

Überprüfen Sie nun anhand von Protokollen, ob Ihre Abfrage nur einmal ausgeführt wird, und deaktivieren Sie den gesamten Debug-Vorgang. Jetzt sind Sie fertig.

Note 2 - Sie können auch missing cache strateg to create definieren, wenn Sie bei den Standardwerten bleiben möchten, ohne Warnungen in Ihren Protokollen zu erhalten:

spring:
  jpa:
    properties:
      hibernate:
        javax:
          cache:
            missing_cache_strategy: create
0