Reputation: 3020
I'm trying to setup Hibernate with EhCache as the second level cache but the TTL is not working.
Here are my dependencies:
<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>
Here's my YAML configuration:
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
Here's how my Entity class is configured:
@Entity
@javax.persistence.Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class PersonEntity {
//
}
And the JpaRepository for the entity:
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);
}
I've configured the cache to expire in 2 seconds, but calling findByName
still uses the cache (there are no SQL Queries printed after the first one).
Here's the ehcache.xml
file:
<?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:
I've done some debugging. I've added a break point in org.ehcache.jsr107.ExpiryPolicyToEhcacheExpiry
:
javax.cache.expiry.Duration duration = this.expiryPolicy.getExpiryForCreation();
This duration is INFINITE for some reason. So maybe the configuration is not set properly? I know the xml is being read because when I invalidate it (by removing heap tag for example) I get an error.
Upvotes: 10
Views: 16932
Reputation: 9492
When you set your @Cacheable
annotation on top of your entity it creates a region where the KEY
is the ID
of the entity and the Value
is the entity. The above mean that you will hit the cache if you access by key which is the ID
. If you use spring data and findById it will hit the cache. If you create a method findByName the access will not be by key trerefore it will not hit the cache region defined by your Cacheable
annotation. On the other hand it will hit the query cache, but the query cache is in entirely different region. And judging from your configuration you have not configured query cache at all.For this method to hit any cache at all you need to add it using this property:
spring:jpa:properties:hibernate:cache:use_query_cache: true
Alternativly you can specify @Cacheable on top of the repository method this way define a new region.
You can configigure default cache, this should capture the StandardQueryCahache.
<defaultCache
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600">
</defaultCache>
In EhCache2 you can configure the standard query cache through this element:
<cache
name="org.hibernate.cache.internal.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="3600"
timeToLiveSeconds="3600">
Not sure how it is in ehcache 3 though. I believe it should be the same, because the StandartQueryCache class is part of the hibernate package and not part of the ehcache package.
I also think you need to set
hibernate.javax.cache.provider = org.ehcache.jsr107.EhcacheCachingProvider
Upvotes: 0
Reputation: 30289
I think I found the cause of the issue - you didn't specify a location of the ehcache.xml
file:
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
in this case Hibernate creates a cache with default configuration. A fragment from my demo project log:
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'.
Upvotes: 17