0
votes

I am trying to implement ehcache to get static data (from table) loaded during application startup however when I make a call again to database, the call is going to database (can see running sql on console) instead of taking values from ehcache.

my code is:

ehcache.xml as below:

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

    <diskStore path="java.io.tmpdir" />

    <cache name="ObjectList"
        maxEntriesLocalHeap="10000"
        maxEntriesLocalDisk="1000"
        eternal="false"
        diskSpoolBufferSizeMB="20"
        timeToIdleSeconds="2000000" timeToLiveSeconds="900000000000"
        memoryStoreEvictionPolicy="LFU"
        transactionalMode="off">
        <persistence strategy="localTempSwap" />
    </cache>
</ehcache>

my repository class is:

public interface customRepository extends JpaRepository<Object, Long> {

  @Cacheable(value = "ObjectList", cacheManager="abclCacheManager")
  public Object findById(Long id);

  @Cacheable(value = "ObjectList", cacheManager="abclCacheManager")
  public List<Object> findAll();
}

and my cacheInitialiser class is:

@Configuration
@EnableCaching
@ComponentScan("com.abcl.process")
public class EhCacheConfiguration {

  @Bean("abclCacheManager")
  public CacheManager cacheManager() {
    return new EhCacheCacheManager(ehCacheCacheManager().getObject());
  }

  @Bean
  public EhCacheManagerFactoryBean ehCacheCacheManager() {
    EhCacheManagerFactoryBean cmfb = new EhCacheManagerFactoryBean();
    cmfb.setConfigLocation(new ClassPathResource("ehcache.xml"));
    cmfb.setShared(true);
    cmfb.setCacheManagerName("abclCacheManager");

    return cmfb;
  }

}

I am testing my this using below:

public class testCache {
  doSomething() { 
    List<Object> listObject = repo.findAll();
    listObject.size();
  }

  public void getOne() { 
    Object o = repo.findById(1L);
  }
}

I can see a db hit in getAll method however I thought the results would get stored in cache and in the second call there would not be a db hit by method getById however I see a db hit on second call as well.

Can anyone please suggest if I am missing anything here.

1

1 Answers

3
votes

When you cache the results of findAll it creates a single entry in the cache which maps the key generated by Spring caching, since your method has no parameter, to the List<Object>. It does not put into the cache one mapping per list element between id and the Object.

So when you use findById(Long), Spring caching will look for a cache entry mapping to the id. And since it cannot find one, it will hit the database.

There is no way of having Spring caching put one mapping per collection element. If that is really what you need, you will have to code it instead of relying on the @Cacheable annotation.