web-dev-qa-db-ja.com

Spring Boot + JPA2 + Hibernate-2次キャッシュを有効にする

JPA2でSpring Boot 1.2.5を使用してエンティティに注釈を付けています(およびJPA実装の基礎として休止状態になっています)。

そのセットアップで2次キャッシュを使用したかったため、エンティティに_@javax.persistence.Cacheable_の注釈が付けられました

また、application.propertiesに以下を追加しました。

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

起動時に休止状態がEhCacheRegionFactoryの欠如について不平を言ったので、私もこれをpomに追加しました:

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

ただし、entityManager.find(Clazz.class, pk)などのクエリは、キャッシュされたデータを使用する代わりにDBクエリを起動しています。

何が欠けているのでしょうか?

22
Daimon

さて、もう少し掘り下げてみると、application.properties

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

それが誰かを助けることを願っています:)

28
Daimon

すべて(L2キャッシュとクエリキャッシュ)を合計するには:

最初に行うことは、キャッシュプロバイダー(EhCacheの使用をお勧めします)をクラスパスに追加することです。

Hibernateの以前のバージョン(5.3より前)では、hibernate-ehcache依存関係を追加することにより行われました。このライブラリには、現在廃止されているEhCache 2が含まれています。

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

Hibernateキャッシュの新しいバージョンでは、JSR-107(JCache)APIを実装する必要があります。そのため、2つの依存関係が必要です。1つはJSR-107 API用で、もう1つは実際のJCache実装(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>

それでは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 

EhCache 3の場合、このリージョンファクトリを使用する必要があります。

factory_class: org.hibernate.cache.jcache.JCacheRegionFactory

HibernateのTRACEレベルのログ記録を有効にして、コードと設定を確認することもできます。

logging:
  level:
    org:
      hibernate:
        type: trace

それでは、コードに移りましょう。エンティティでL2キャッシングを有効にするには、これらの2つのアノテーションを追加する必要があります。

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

-@OneToManyまたは@ManyToOne関係をキャッシュする場合-このフィールドに@Cache注釈を追加しますまあ。

また、spring-data-jpaリポジトリでクエリキャッシュを有効にするには、適切なQueryHintを追加する必要があります。

public class MyEntityRepository implements JpaRepository<MyEntity, Long> {

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

}

クエリが1回だけ実行されたかどうかをログで確認し、すべてのデバッグ機能をオフにすることを忘れないでください。これで完了です。

注2- missing cache strategy as createとしても定義できます。ログに警告が表示されます:

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

@ Daimon 本当にわからない

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

最良の決定です。

Hibernate 20.2.1。キャッシュマッピングドキュメントセクション から引用

デフォルトでは、エンティティは2次キャッシュの一部ではないため、この設定を維持することをお勧めします。ただし、persistence.xmlファイルでshared-cache-mode要素を設定するか、構成でjavax.persistence.sharedCache.modeプロパティを使用して、これをオーバーライドできます。

一方、

ENABLE_SELECTIVE(デフォルトおよび推奨値):エンティティは、明示的にキャッシュ可能としてマークされていない限りキャッシュされません。

したがって、影響を受けるすべてのエンティティに@ javax.persistence.Cacheableまたは@ org.hibernate.annotations.Cacheで注釈を付けていない可能性がありますか?これにより、クエリキャッシュが2番目のレベルキャッシュ内で影響を受けるエンティティを正常に検索しようとし、単一の選択で各エンティティのフェッチを開始するという影響が生じる可能性があります。

7
GeBeater

追加しましたか

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

キャッシュしたいクラスで?

2
m1416

クラスパスにehcache.xmlファイルが必要です。ファイルには、少なくともデフォルトのキャッシュ戦略が含まれている必要があります。デバッグを簡単にするために、エンティティがキャッシュから削除されないことを確実にすることを永遠にします。

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"
...
/>
_

すべてが正常であることを確認するには、アプリケーションの起動中に次のログを取得する必要があります。

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

これは、エンティティキャッシュアノテーションが正しく読み取られ、デフォルトのキャッシュが使用されることを意味します。

entityManager.find(Clazz.class, pk)を使用してテストする場合、クエリキャッシュではなく、エンティティキャッシュのみが関与します。クエリキャッシュは、クエリ(em.createQuery(...)およびリレーションシップに使用されます

また、私はorg.hibernate.cache.ehcache.SingletonEhCacheRegionFactoryを使用しますが、私がより良いとは知りません。

0
crv

JCache、Ehcache、Gvava Cache、Hazelcast Cache、Caffeine Cacheのうち、サードパーティのキャッシュプロバイダーを使用できます。

Quora のこの回答を参照して、Springブートで2次キャッシュを有効にして構成する方法を確認してください。

0
Arun Raaj