Как правильно настроить двухуровневый кеш сущностей спящего режима с помощью аннотаций

Я хочу настроить кеш гибернации 2-го уровня в микросервисе Spring Boot. И я вообще не хочу использовать xml. Дальше мой пример.

UserEntity.java

@Entity
@Table(name = "users")
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE, region = "users")
public class UserEntity {

    @Id
    private long id;

    @Column
    private String name;

    public UserEntity(long id, String name) {
        this.id = id;
        this.name = name;
    }

   // ... geters&setters
}

CacheConfig.java

import net.sf.ehcache.config.CacheConfiguration;
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.ehcache.EhCacheCacheManager;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableCaching
public class CacheConfig {

    @Bean
    public org.springframework.cache.CacheManager cacheManager() {
        return new EhCacheCacheManager(ehCacheManager());
    }

    private net.sf.ehcache.CacheManager ehCacheManager() {

        CacheConfiguration usersCacheConfiguration = new CacheConfiguration();
        usersCacheConfiguration.setName("users");
        usersCacheConfiguration.eternal(false);
        usersCacheConfiguration.setMaxEntriesInCache(1000);
        usersCacheConfiguration.setMaxEntriesLocalDisk(0);
        usersCacheConfiguration.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LRU);

        net.sf.ehcache.config.Configuration config = new net.sf.ehcache.config.Configuration();
        config.addCache(usersCacheConfiguration);

        return net.sf.ehcache.CacheManager.create(config);
    }
}

App.java

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        new SpringApplicationBuilder(App.class)
                .sources(CacheConfig.class)
                .run(args);
    }

}

приложение.свойства

spring:
  datasource:
    url: jdbc:postgresql://localhost:5432/test
    username: postgres
    password: postgres
    type: com.zaxxer.hikari.HikariDataSource
    driverClassName: org.postgresql.Driver
  jpa.hibernate.ddl-auto: update
  jpa.open-in-view: false
  jpa.properties.javax.persistence.sharedCache.mode: ALL
  jpa.properties.hibernate:
    dialect: org.hibernate.dialect.PostgreSQL9Dialect
    jdbc.batch_size: 100
    temp.use_jdbc_metadata_defaults: false
    order_inserts: true
    cache:
      region.factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory
      #region.factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory
      #region_prefix: ""
      use_second_level_cache: true
      cache.use_query_cache: true
      provider_class: org.hibernate.cache.EhCacheProvider

build.gradle

group 'com.hibernate.cache'
version '1.0-SNAPSHOT'

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.springframework.boot', name: 'spring-boot-starter-data-jpa', version: '2.0.0.RELEASE'
    compile group: 'org.springframework', name: 'spring-context-support', version: '5.0.4.RELEASE'
    compile group: 'org.hibernate', name: 'hibernate-ehcache', version: '5.2.14.Final'
    compile group: 'org.postgresql', name: 'postgresql', version: '42.1.4'
}

Когда я запускаю программу, я вижу пару предупреждений, указывающих, что конфигурация кэша сущностей не применяется:

2018-03-04 23:29:48.723  WARN 8516 --- [           main] n.s.ehcache.config.ConfigurationFactory  : No configuration found. Configuring ehcache from ehcache-failsafe.xml  found in the classpath: jar:file:/home/vitaly/.gradle/caches/modules-2/files-2.1/net.sf.ehcache/ehcache/2.10.3/cf74f9a4a049f181833b147a1d9aa62159c9d01d/ehcache-2.10.3.jar!/ehcache-failsafe.xml
2018-03-04 23:29:48.834  WARN 8516 --- [           main] o.h.c.e.AbstractEhcacheRegionFactory     : HHH020003: Could not find a specific ehcache configuration for cache named [users]; using defaults.

Кто-нибудь знает, что здесь не так?


person rvit34    schedule 04.03.2018    source источник
comment
Нашел решение здесь - stackoverflow.com/a/21944585/7022735   -  person rvit34    schedule 05.03.2018


Ответы (2)


Первое предупреждение:

2018-03-04 23:29:48.723  WARN 8516 --- [           main] n.s.ehcache.config.ConfigurationFactory  : No configuration found. Configuring ehcache from ehcache-failsafe.xml  found in the classpath: jar:file:/home/vitaly/.gradle/caches/modules-2/files-2.1/net.sf.ehcache/ehcache/2.10.3/cf74f9a4a049f181833b147a1d9aa62159c9d01d/ehcache-2.10.3.jar!/ehcache-failsafe.xml

означает, что конфигурация ehcache.xml не найдена, поэтому используется файл ehcache-failsafe.xml по умолчанию.

Второе предупреждение:

2018-03-04 23:29:48.834  WARN 8516 --- [           main] o.h.c.e.AbstractEhcacheRegionFactory     : HHH020003: Could not find a specific ehcache configuration for cache named [users]; using defaults.

означает, что в кеше не найдена конфигурация для региона «users». Это, конечно, не определено в ehcache-failsafe.xml, и не похоже, что настройки в CacheConfig подхватываются — по крайней мере, не CacheManager, используемым Hibernate.

Должна быть возможность решить оба вопроса, добавив ehcache.xml в путь к классам (в src/main/resources), например:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
         updateCheck="true"
         monitoring="autodetect"
         dynamicConfig="true">

    <cache name="users"
           maxEntriesLocalHeap="500"
           eternal="false"
           timeToIdleSeconds="300"
           timeToLiveSeconds="600"
           diskExpiryThreadIntervalSeconds="1"
           copyOnRead="true"
           copyOnWrite="true">
        <copyStrategy class="net.sf.ehcache.store.compound.ReadWriteSerializationCopyStrategy" />
    </cache>

</ehcache>

(дополнительные параметры см. в этом образце ehcache.xml)

И добавляем в application.yml следующее:

spring:
  cache:
    ehcache:
      config: classpath:ehcache.xml
person codemonkey    schedule 04.03.2018
comment
Спасибо за ваш подробный ответ. Но могу ли я сделать то же самое без xml? - person rvit34; 05.03.2018

С опозданием на год, но ответ на ваш вопрос может потребовать от вас реализовать свой собственный класс RegionFactory (путем расширения SingletonEhCacheRegionFactory), а затем установить только что созданный класс в качестве фабрики, которую должен использовать спящий режим: spring.jpa.properties.hibernate.cache.region. factory_class=com.my.class https://stackoverflow.com/a/28594371/708854

person Yaz    schedule 11.03.2019