0

We have set up JPA second-level cache but not working with the following configuration cache is configured properly as per logging but it not cache the database result and always fetching data from the database.

11:44:07.454 [main] [UserId: ] WARN net.sf.ehcache.Cache - Cache: com.Record has a maxElementsInMemory of 0.  In Ehcache 2.0 this has been changed to mean a store with no capacity limit. Set it to 1 if you want no elements cached in memory.

ehcache.xml

<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="ehcache.xsd" updateCheck="true" monitoring="autodetect" dynamicConfig="true">
   <defaultCache eternal="false" timeToLiveSeconds="10000" memoryStoreEvictionPolicy="LFU" statistics="true" maxElementsInMemory="10000" overflowToDisk="false" />
   <cache maxElementsInMemory="10000" name="Record"  eternal="false" timeToIdleSeconds="10000" timeToLiveSeconds="10000" memoryStoreEvictionPolicy="LFU" statistics="true" />
</ehcache>

Enabled spring boot Caching in Application.java

@SpringBootApplication
@EnableScheduling
@EnableCaching
public class Application extends SpringBootServletInitializer {


    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(Application.class);
    }

      @PostConstruct
      public void init(){
        // Setting Spring Boot SetTimeZone
        TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
      }
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

Entity Record.java

@Entity
@EntityListeners(AuditingEntityListener.class)
@Table(name = "t_record")
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn(name = "c_discriminator", discriminatorType = DiscriminatorType.STRING)
@Cacheable
@org.hibernate.annotations.Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region = "Record")
@NamedQueries({@NamedQuery(name = Record.QUERY_findAllByType, query = "SELECT r FROM Record r WHERE TYPE(r) = ?1 ORDER BY r.date DESC, r.id DESC")})
public abstract class Record implements Cloneable, XmlOutputEntity {

    /**
     * Class UID
     */
    private static final long serialVersionUID = 7146308281386143748L;
    
    public static final String QUERY_findAllByType = "findAllRecordByType";
    
}

Enabled second-level cache and query cache in the database configuration.

@Configuration
public class DatabaseConfig {

    protected PropConfig propConfig;

    @Autowired
    public DatabaseConfig(PropConfig propConfig) {
        this.propConfig = propConfig;
    }

    
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(propConfig.getDatabaseDriver());
        dataSource.setUrl(propConfig.getDatabaseUrl());
        dataSource.setUsername(propConfig.getDatabaseUsername());
        dataSource.setPassword(propConfig.getDatabasePassword());
        return dataSource;
    }


    @Bean
    public LocalValidatorFactoryBean validator() {
        final LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
        return validator;
    }

    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource,JpaVendorAdapter jpaVendorAdapter) {

        LocalContainerEntityManagerFactoryBean lef = new LocalContainerEntityManagerFactoryBean();
        lef.setDataSource(dataSource);
        lef.setJpaVendorAdapter(jpaVendorAdapter);
        lef.setPackagesToScan("com.test");

        Properties props = new Properties();
        props.put("logging.level.org.hibernate.SQL", "true");
        props.put("logging.level.org.hibernate.type.descriptor.sql.BasicBinder", "TRACE");
        props.put("show-sql", "true");
        lef.setJpaProperties(props);

        lef.getJpaPropertyMap().put("jadira.usertype.autoRegisterUserTypes", "true");
        lef.getJpaPropertyMap().put("hibernate.ejb.naming_strategy", "org.hibernate.cfg.ImprovedNamingStrategy");
        lef.getJpaPropertyMap().put("hibernate.temp.use_jdbc_metadata_defaults", "false");
        lef.getJpaPropertyMap().put("hibernate.cache.use_second_level_cache", "true");
        lef.getJpaPropertyMap().put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory");
        lef.getJpaPropertyMap().put("hibernate.cache.use_query_cache", "true");
        lef.setSharedCacheMode(SharedCacheMode.ALL);
        return lef;
    }

    @Bean
    public JpaVendorAdapter jpaVendorAdapter() {
        HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
        hibernateJpaVendorAdapter.setShowSql(propConfig.isShowSql());
        hibernateJpaVendorAdapter.setGenerateDdl(propConfig.isGenerateDdl());
        hibernateJpaVendorAdapter.setDatabase(propConfig.getVendor());
        return hibernateJpaVendorAdapter;
    }

    @Bean
    public PlatformTransactionManager transactionManager() {
        return new JpaTransactionManager();
    }
}

1 Answers1

1

Query caching has to be enabled on a case by case basis by setting the org.hibernate.cacheable hint to true. I think with Spring Data JPA you have to annotate the repository method with @QueryHint(name = "org.hibernate.cacheable", value = "true")

Christian Beikov
  • 15,141
  • 2
  • 32
  • 58