Spring Boot 2.0 Hibernate 5 EhCache 3 с JCache - PullRequest
0 голосов
/ 24 мая 2019

Я пытаюсь настроить Hibernate с EhCache в качестве кэша второго уровня, но TTL не работает.

Вот мои зависимости:

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

Вот моя конфигурация 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

Вот как настроен мой класс Entity:

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

И JpaRepository для сущности:

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);
}

Я настроил срок действия кэша через 2 секунды, но при вызове findByName по-прежнему используется кэш (после первого запроса SQL не напечатано).

Вот файл ehcache.xml:

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

РЕДАКТИРОВАТЬ: Я сделал некоторые отладки.Я добавил точку останова в org.ehcache.jsr107.ExpiryPolicyToEhcacheExpiry:

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

По какой-то причине эта длительность БЕСКОНЕЧНА.Так, может быть, конфигурация не установлена ​​правильно?Я знаю, что xml читается, потому что когда я делаю его недействительным (например, удаляя тег heap), я получаю сообщение об ошибке.

enter image description here

Ответы [ 2 ]

1 голос
/ 30 мая 2019

Я думаю, что нашел причину проблемы - вы не указали расположение файла ehcache.xml:

spring:
  jpa:
    properties:
      hibernate:
        javax.cache:
          provider: org.ehcache.jsr107.EhcacheCachingProvider
          uri: classpath:ehcache.xml
        cache:
          use_second_level_cache: true
          region.factory_class: jcache
          use_query_cache: true

в этом случае Hibernate создает кеш с конфигурацией по умолчанию. Фрагмент из журнала моего демо-проекта:

17:15:19 WARN [main] org.hibernate.orm.cache: HHH90001006: Missing cache[user] was created on-the-fly. The created cache will use a provider-specific default configuration: make sure you defined one. You can disable this warning by setting 'hibernate.javax.cache.missing_cache_strategy' to 'create'.
0 голосов
/ 29 мая 2019

Когда вы устанавливаете аннотацию @Cacheable поверх вашей сущности, она создает область, в которой KEY является ID сущности, а Value - сущностью. Вышеуказанное означает, что вы попадете в кеш, если получите доступ по ключу, который является ID. Если вы используете данные весны и findById, он попадет в кеш. Если вы создадите метод findByName, доступ не будет осуществляться по ключу, поэтому он не попадет в область кэша, определенную вашей аннотацией Cacheable. С другой стороны, он попадет в кеш запросов, но кеш запросов находится в совершенно другом регионе. И, судя по вашей конфигурации, вы вообще не настроили кеш запросов. Чтобы этот метод ударил любой кеш, вам нужно добавить его с помощью этого свойства:

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

В качестве альтернативы вы можете указать @Cacheable поверх метода хранилища, чтобы определить новый регион.

Вы можете настроить кэш по умолчанию, он должен захватывать StandardQueryCahache.

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

В EhCache2 вы можете настроить стандартный кеш запросов через этот элемент:

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

Не уверен, как в ehcache 3. Я полагаю, что так должно быть, потому что класс StandartQueryCache является частью пакета hibernate, а не частью пакета ehcache.

Я также думаю, что вам нужно установить
hibernate.javax.cache.provider = org.ehcache.jsr107.EhcacheCachingProvider

...