Hello everybody,

Greetings of the day!

Today we will learn about caching, and how we can implement caching with Spring Boot so let's begin.

Often there are specific data that is frequently used that does not change often. You can improve performance by caching such data instead of retrieving it from the database each time.

Examples of such data include lists of countries, states, and currencies.

Today you will learn how to easily implement caching using Spring Boot with REST API. First, go to Spring Initializr, generate a project with the following dependencies, and open the project in your preferred IDE.


Example description.
  • This example uses PostgreSQL.
  • Develop a Rest API that lists all the currencies available in your database.
  • Cache the rest of the APIs above to avoid hitting the database to get the list of currencies each time the list currency API is called.
  • Develop a REST API to clear the cache. Therefore, whenever currency-related data changes (which doesn't happen very often), you can call the REST API to clear the existing cache. Once the cache is cleared, Spring will use the database to retrieve the updated currency and cache the new set of currencies the next time the list currency API is called. 
Now let's start developing.

Since this example uses PostgreSQL, add database-related properties to the application.properties file.

spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=add_your_db_username
spring.datasource.password=add_your_db_password
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto = update

Next, let's create a Currency.java class under the entity package that maps to the currency table in the database.


Next, let's create a CurrencyDTO.java class under the dto package that will be used to send the response to our REST API caller.

Next, let's create a repository layer for retrieving currencies from the database. Since we are using Spring JPA here, create a CurrencyRepository.java interface under the repository package that extends JpaRepository as shown below.



To enable caching, you need to add the @EnableCaching annotation above any configuration class or with the @SpringBootApplication annotation.

Note - We already added the spring cache dependency to our project during configuration, but if you have an existing project, you need to add the following dependency to your pom.xml:

<dependency>

<groupId>org.springframework.boot</groupId>

<artifactId>spring-boot-starter-cache</artifactId>

</dependency>

Next, let's create a service layer that caches the list of currencies using the @Cacheable annotation. Now let's create the CurrencyService interface and the CurrencyServiceImpl.java class under the service and service impl packages respectively.

CurrencyService.java


CurrencyServiceImpl.java

So here I used @Cacheable(cacheNames="currencies") over the list currency method. The first time this service layer method is called, currencyRepository.findAll() is called and the result is cached with the cache name currency. Subsequent calls will return results from the cache itself.

Next, let's create a CurrencyController.java under the controller package to define the REST API for listing currencies.

Now let's add an endpoint to flush the cache. So add the CacheService.java interface and CacheServiceImpl.java class under the service and service impl packages respectively.

CacheService.java

CacheServiceImpl.java

The code above uses the CacheManager clear method to clear the cache using the cache name.

Now let's add an API endpoint that calls this service to clear the cache. So add a CacheController under the controller package and call CacheService.

CacheController.java

Also, add the following property to your application.properties to log the executed SQL queries so you can see if the cache actually worked or not.

logging.level.org.hibernate.SQL=DEBUG

logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

We are done with all configurations needed for caching, so it's time for some testing so let's start the application.

First, let's add some records to the Currency table in PostgresSQL using the following query.

insert into currency values (1,'INR','₹');

insert into currency values (2,'USD','$');

Now let's get all the currencies by accessing the RESP API at the following URL:

http://localhost:8080/currency/list


You can now observe the logs. You can see that the following query is executed only once no matter how many times you hit http://localhost:8080/currency/list

select currency0_.id as id1_0_, currency0_.currency as currency2_0_, currency0_.currency_symbol as currency3_0_ from currency currency0_

Let's add another record to the currency table using the following query.

insert into currency values (3,'EUR','€');

Now again hit API http://localhost:8080/currency/list 

As you can see below,  EUR currency is not loaded in response because Spring is using data from the cache instead of the database.


We already have an endpoint for updating the cache, so hit

http://localhost:8080/cache/clear?cacheName=currencies

Note: Since we saved the cache using the cacheName currency, we pass that in the URL above.


After calling the above endpoint to update the cache, call the API to list the currencies.


So, as you can see in the response EUR record is also coming, the data is retrieved from the database and cached again since the existing cache was cleared.

We've seen how to implement caching and flush caches in Spring Boot. If you have any doubts or problems implementing the example above, let us know in the comments section.

Thanks

Enjoy your learning!

Other articles for reference