In this post, we will see Hibernate/JPA EhCache Configuration Example Using Spring Boot and Oracle. We are going to use Hibernate 5 and Spring Boot 2.x for this tutorial.
Introduction.
EhCache is used for second-level cache to reduce the number of queries in the database and for performance improvement. Hibernate provides inbuilt support for EhCache and Infinispan. Here we will see hibernate second level cache example using EhCache.
First, we will save one record in the database, and then we will retrieve it from EhCache.
Note – EhCache stores the data in In-Memory and Disk. Check other second level cache example.
Spring boot second level cache example using Hazelcast
Spring boot second level cache example using Redis.
Maven Dependency.
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
</dependency>
Hibernate EhCache Configuration.
Step 1 – Enable second level cache and configure EhCacheRegionFactory(EhCacheProvider is deprecated). We need to make the below changes in the application.properties file.
spring.jpa.properties.hibernate.cache.use_second_level_cache=true
spring.jpa.properties.hibernate.cache.use_query_cache=true
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory
Step 2 – Define ehcache.xml in the resources folder.
<?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="30"
memoryStoreEvictionPolicy="LRU" statistics="true" maxElementsInMemory="10000"
overflowToDisk="false" />
<cache name="book" maxEntriesLocalHeap="10000" eternal="false"
timeToIdleSeconds="60" timeToLiveSeconds="60" memoryStoreEvictionPolicy="LRU"
statistics="true">
</cache>
</ehcache>
Step 3 – Use @Cacheable and @Cache annotation with the entity.
@Entity
@Cacheable
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region = "book" )
public class Book implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private int bookId;
@Column(name = "book_name")
private String bookName;
}
Hibernate/JPA EhCache Configuration Example Using Spring Boot and Oracle from Scratch(read-only).
Open eclipse and create maven project, Don’t forget to check ‘Create a simple project (skip)’ click on next. Fill all details(GroupId – hibernateehcache, ArtifactId – hibernateehcache and name – hibernateehcache) and click on finish. Keep packaging as the jar.
Modify pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>hibernateehcache</groupId> <artifactId>hibernateehcache</artifactId> <version>0.0.1-SNAPSHOT</version> <name>hibernateehcache</name> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.1.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> </dependency> <!-- oracle maven dependency --> <dependency> <groupId>com.oracle</groupId> <artifactId>ojdbc6</artifactId> <version>11.2.0.3</version> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> </dependency> </dependencies> </project>
If you see any error for oracle dependency then follow these steps.
Directory structure –
Student.java
package com.javatute.entity; import java.io.Serializable; import javax.persistence.Cacheable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import org.hibernate.annotations.Cache; import org.hibernate.annotations.CacheConcurrencyStrategy; @Entity @Cacheable @Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region = "book" ) public class Book implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private int bookId; @Column(name = "book_name") private String bookName; public int getBookId() { return bookId; } public void setBookId(int bookId) { this.bookId = bookId; } public String getBookName() { return bookName; } public void setBookName(String bookName) { this.bookName = bookName; } }
StudentController.java
package com.javatute.controller; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.javatute.entity.Book; import com.javatute.service.BookService; @RestController @RequestMapping(value = "/book") public class BookController { @Autowired private BookService bookService; @RequestMapping(value = "/savebook", method = RequestMethod.POST) @ResponseBody public Book saveBook(@RequestBody Book book) { Book bookResponse = bookService.saveBook(book); return bookResponse; } @RequestMapping(value = "/{bookId}", method = RequestMethod.GET) @ResponseBody public Book getBookDetails(@PathVariable int bookId) { Book bookResponse = bookService.findById(bookId); return bookResponse; } }
Note – See more details about @Controller and RestController here.
StudentRepository.java – interface
package com.javatute.repository; import java.io.Serializable; import org.springframework.data.repository.CrudRepository; import org.springframework.stereotype.Repository; import com.javatute.entity.Book; @Repository public interface BookRepository extends CrudRepository<Book,Serializable> { }
StudentService.java – interface
package com.javatute.service; import org.springframework.stereotype.Component; import com.javatute.entity.Book; @Component public interface BookService { public Book saveBook(Book book); public Book findById(int bookId); }
Note – See here more about @Component, @Controller, @Service and @Repository annotations here.
StudentServiceImpl.java
package com.javatute.serviceimpl; import java.util.Optional; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import com.javatute.entity.Book; import com.javatute.repository.BookRepository; import com.javatute.service.BookService; @Service("bookServiceImpl") public class BookServiceImpl implements BookService { @Autowired private BookRepository bookRepository; @Transactional @Override public Book saveBook(Book book) { book = bookRepository.save(book); return book; } @Transactional public Book findById(int bookId) { Optional<Book> bookResponse = bookRepository.findById(bookId); return bookResponse.get(); } }
SpringMain.java
package com.javatute.main; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.domain.EntityScan; import org.springframework.context.annotation.ComponentScan; @SpringBootApplication @ComponentScan(basePackages="com.javatute.*") @EntityScan("com.javatute.*") public class SpringMain { public static void main(String[] args) { SpringApplication.run(SpringMain.class, args); } }
Note – See more details about @ComponentScan here.
JpaConfig.java
package com.javatute.config; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Configuration; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; @Configuration @EnableJpaRepositories(basePackages = "com.javatute.repository") @EnableCaching public class JpaConfig { }
Note – See more details about @Configuration annotations here.
application.properties
# Connection url for the database spring.datasource.url=jdbc:oracle:thin:@localhost:1521:XE spring.datasource.username=SYSTEM spring.datasource.password=oracle spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver # Show or not log for each sql query spring.jpa.show-sql = true spring.jpa.properties.hibernate.format_sql=true spring.jpa.hibernate.ddl-auto =create spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.Oracle10gDialect server.port = 9091 #show sql values logging.level.org.hibernate.type.descriptor.sql=trace #spring.jpa.hibernate.logging.level.sql =FINE #show sql statement #logging.level.org.hibernate.SQL=debug spring.jpa.properties.hibernate.cache.use_second_level_cache=true spring.jpa.properties.hibernate.cache.use_query_cache=true spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory #spring.cache.type=ehcache #spring.cache.ehcache.config=classpath:ehcache.xml
The spring.jpa.properties.hibernate.cache.use_second_level_cache=true is used to enabled second level cache.
The spring.jpa.properties.hibernate.cache.use_query_cache=true is used to enable Query Cache.
spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory is EhCache provider.
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="30" memoryStoreEvictionPolicy="LRU" statistics="true" maxElementsInMemory="10000" overflowToDisk="false" /> <cache name="book" maxEntriesLocalHeap="10000" eternal="false" timeToIdleSeconds="60" timeToLiveSeconds="60" memoryStoreEvictionPolicy="LRU" statistics="true"> </cache> </ehcache>
Testing of example using postman.
Let’s run the SpringMain class(run as java application).
Perform save operation first using below REST API.
{
"bookName": "Alchemist"
}
Response Data.
Now perform get operation.
GET- http://localhost:9091/book/1
Since we have defined time 60 seconds in ehcache.xml for the book, EhCache will store data in In-Memory for 60 seconds. For testing, hit the get URL(https://localhost:9091/book/1) multiple times from the postman and observe the console(since we have defined spring.jpa.show-sql = true
in application.properties file query will print at the console) hibernate will not fire select query.
After 60 seconds if you again perform get operation, hibernate will fire the select query and for the next 60 seconds, you can retrieve data from the EhCache.
Note – Change the value of spring.jpa.properties.hibernate.cache.use_second_level_cache=false and restart the application and perform save operation. Now perform retrieve operation multiple times and observe the console. Hibernate will fire the query for each request since we have disabled the second level cache.
Hibernate/JPA EhCache example for Collection Types( OneToMany association).
In this section, we will see how to implement Hibernate/JPA EhCache for OneToMany association mapping. Suppose we have two entities Book and Story which are OneToMany relationship(one book can have many stories).
In this case below EhCache configuration and code change needed.
Define new cache for child(Story) entity in ehcache.xml.
<cache name="story" maxEntriesLocalHeap="10000" eternal="false"
timeToIdleSeconds="20" timeToLiveSeconds="20"
memoryStoreEvictionPolicy="LRU" statistics="true">
</cache>
Entity level changes.
We need to define @Cache annotation with the child field(storyList).
@OneToMany(cascade = CascadeType.ALL, fetch= FetchType.LAZY)
@JoinColumn(name = "book_id",referencedColumnName="bookId")
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region = "story" )
private List<Story> storyList = new ArrayList<>();
We need to use @Cacheable and @Cache annotation with the child entity(Story.java).
@Entity
@Cacheable
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
public class Story {
}
Book.java
@Entity @Cacheable @Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region = "book" ) public class Book implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private int bookId; @Column(name = "book_name") private String bookName; @OneToMany(cascade = CascadeType.ALL, fetch= FetchType.LAZY) @JoinColumn(name = "book_id",referencedColumnName="bookId") @Cache(usage=CacheConcurrencyStrategy.READ_ONLY, region = "story" ) private List<Story> storyList = new ArrayList<>(); //getter & setter }
Story.java
@Entity @Cacheable @Cache(usage=CacheConcurrencyStrategy.READ_ONLY) public class Story { @Id @GeneratedValue(strategy = GenerationType.AUTO) private int storyId; @Column(name = "story_name") private String storyName; }
Note – The rest of the code would be the same.
HQL EhCache example(Enabling query cache).
We need to add spring.jpa.properties.hibernate.cache.use_query_cache=true
in application.properties.
Defining the HQL method to retrieve the data.
@Transactional
public Book getBookUsingHQL(int bookId) {
String hql = "FROM Book b WHERE b.bookId = :bookId";
Query query = entityManager.createQuery(hql, Book.class);
query.setParameter("bookId", bookId);
query.setHint( "org.hibernate.cacheable", "true");
List<Book> books = query.getResultList();
return books.get(0);
}
Cache concurrency strategy in Hibernate.
There are four cache concurrency strategies supported by the hibernate.
- Read-Only
- Read-Write
- Nonstrict-Read-Write
- Transactional
Read-Only cache concurrency strategy.
We have already seen CacheConcurrencyStrategy.READ_ONLY example. As the name suggests, this cache concurrency strategy is useful when we have to perform read-only operation. In this cache strategy if we will try to perform the update operation we might get java.lang.UnsupportedOperationException: Can't update readonly object.
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "book")
public class Book implements Serializable {
}
The read-only strategy is useful for search/retrieval operation.
Read-Write cache concurrency strategy.
Using CacheConcurrencyStrategy.READ_WRITE we can perform update operation too.
@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class Book implements Serializable {
}
Nonstrict-Read-Write Cache concurrency strategy.
Similar to read-write strategy but there might be occasional stale reads upon concurrent access to an entity.
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Book implements Serializable {
}
Transactional cache concurrency strategy.
Provides serializable transaction isolation level.
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class Book implements Serializable {
}
That’s all about Hibernate/JPA EhCache Configuration Example Using Spring Boot and Oracle.
Download complete source code from github.
You may like.
Spring Data JPA examples.
- Spring Data JPA Query Methods.
- Spring Data JPA greater than Example.
- Spring Data JPA less than Example.
- Spring Data JPA IsNull Example Using Spring Boot.
- Spring Data findById() Vs getOne()
- Spring Data JPA CrudRepository findById()
- Spring Data JPA JpaRepository getOne()
- Spring Data CrudRepository saveAll() and findAll().
- Spring Data CrudRepository existsById()
- Spring Data JPA delete() vs deleteInBatch()
- Spring Data JPA deleteAll() Vs deleteAllInBatch()
- Spring Data JPA JpaRepository deleteAllInBatch()
- Spring Data JPA deleteInBatch() Example
- Spring Data JPA JpaRepository saveAndFlush() Example
- Spring Data JPA CrudRepository count() Example
- Spring Data JPA CrudRepository delete() and deleteAll()
- Spring Data JPA CrudRepository deleteById() Example
- CrudRepository findAllById() Example Using Spring Boot
Hibernate association mapping using Spring Boot.
- One To One Mapping Annotation Example in Hibernate/JPA using Spring Boot and Oracle.
- One To One Bidirectional Mapping Example In Hibernate/JPA Using Spring Boot and Oracle.
- One To Many Mapping Annotation Example In Hibernate/JPA Using Spring Boot And Oracle.
- Many To One Unidirectional Mapping In Hibernate/JPA Annotation Example Using Spring Boot and Oracle.
- One To Many Bidirectional Mapping In Hibernate/JPA Annotation Example Using Spring Boot and Oracle.
- Many To Many Mapping Annotation Example In Hibernate/JPA Using Spring Boot And Oracle.
Hibernate EhCache documentation.
Summary – We have seen about Hibernate/JPA EhCache Configuration Example using Spring boot and Oracle.