AdBlock Detected

It looks like you're using an ad-blocker!

Our team work realy hard to produce quality content on this website and we noticed you have ad-blocking enabled. Advertisements and advertising enable us to continue working and provide high-quality content.

Implementing a Cache with Spring

Implementing a cache with Spring is a fairly easy task, thanks to its ease of implementation. For this purpose, Spring provides us with a series of annotations that we will see in the rest of the tutorial.

What is a cache?

A cache is a way or mechanism to improve the performance of a microservice/service or application. It can temporarily store necessary information, usually in memory, in order to retrieve it quickly.

This information is often stored in memory and can be used to reduce the number of times we access a database.

Why should we use a cache?

Many times, the same operations are performed against a database, such as retrieving all holidays for a country. Since we know that this information won’t change, we can store it in a cache. This information will be stored in memory (most of the time), and its retrieval will be much faster.

Types of caches

In-memory: This is the best mechanism to improve the performance of any application since we know that RAM is faster than any other system. However, it is also more scarce and expensive than disk storage, so we need to consider invalidation mechanisms like LRU (Least Recently Used). Some in-memory caches can be Redis and Memcached.

Database cache: Generally, databases also implement some level of cache. Well-known examples are the first-level cache in Hibernate.

Web servers and CDNs: Both are aimed at serving web content at a higher speed by caching static content. Examples include Varnish, which avoids making requests, and browser-based caches.

Cache with Spring Boot

Integrating a cache into a Spring project is really straightforward, using annotations and the Spring Cache starter.

Spring provides an abstraction layer to use different cache providers by overriding the CacheManager. However, in this example, we will only use Spring’s default cache.

Including the dependency

To begin with, we would include the Maven dependency in our project:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
    <version>2.2.4.RELEASE</version>
</dependency>

Enabling the cache in Spring

@EnableCaching: This annotation, placed alongside the @SpringBootApplication annotation in the main class of the project, grants our application the caching capabilities of Spring. By default, it uses a concurrent HashMap, but as mentioned earlier, we can replace it by adding other external caches.

Using the cache

To use the cache in spring we can use different annotations:

@Cacheable: To allow our application to use the cache, we need to add the @Cacheable annotation to the methods. This way, Spring knows which method responses can be cached.

@CachePut: This annotation allows us to update a cache. It works similarly to @Cacheable.

@CacheEvict: This annotation allows us to remove previously cached information. We can either remove all caches or specify the cache we want to remove by its key.

@Caching: This annotation is necessary when we want to use both @CacheEvict and @CachePut together.

NOTE: We should never use @CachePut and @CacheEvict on the same method simultaneously, as it could lead to undesired effects.

Let’s get to work.

Next, we’ll create a system that caches all holidays in Spain implementing a Cache with Spring:

@SpringBootApplication
public class StratioSpringBootService {

  public static void main(String[] args) {
    SpringApplication.run(StratioSpringBootService.class, args);
  }
}

We create or activate the configuration by adding the @EnableCaching annotation to a configuration class. We can also add the cacheManager bean in this class.

@Configuration
@EnableCaching
public class CachingConfig {
 
    @Bean
    public CacheManager cacheManager() {
        return new ConcurrentMapCacheManager("holidays");
    }
}

Next, We are going to generate the domain object Holiday:

  @Getter
  @Setter
  public class Holiday {

    private Long id;

    private LocalDate day;
  }

We create the service layer that will interact with the repository and will be responsible for caching the holidays:

  @Getter
  @Setter
  @AllArgsConstructor
  public class HolidayServiceImpl implements HolidayService{

    private final HolidayRepository holidayRepository;
    

   @Cacheable("holidays")
   public List<Holiday> findAll() {
   return  holidayRepository.findAll();
   }
  }

With the above code snippet, we have cached all the holidays returned by the repository. The first time it is called, it will fetch the data from the database, and subsequent calls will retrieve the data from the defined cache, in this case, the default Spring concurrent hashmap. This is a very basic exercise that only demonstrates the principles of using a cache in Spring. It’s important to consider update and eviction policies, connection with third-party caches like Redis, Ignite, etc.

You can find this example on GitHub by clicking here. For more information, you can refer to the official documentation here.

Conclusion

In this post about Implementing a Cache with Spring we have seen how we can add a Cache in our Spring Application. Using cache in Spring improves application performance by storing and retrieving frequently accessed data quickly, reducing database calls.

If you need more information, you can leave us a comment or send an email to refactorizando.web@gmail.com You can also contact us through our social media channels on Facebook or twitter and we will be happy to assist you!!

Leave a Reply

Your email address will not be published. Required fields are marked *