Spring Data Redis Cache

By Arvind Rai, November 30, 2023
On this page I will create Spring Data application using Redis Cache. We willl learn to integrate Redis with Spring Data application and perform caching for our data obtained from database.

1. Maven Depedency

Find the Maven file used in the demo application.
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency> 

2. Redis Connection Factory

To get connections for Redis server, Spring provides LettuceConnectionFactory and JedisConnectionFactory.
1. Using LettuceConnectionFactory
LettuceConnectionFactory creates Lettuce connections. It requires lettuce-core which is provided by Spring Boot 2.0 by default using the starter spring-boot-starter-data-redis. Find the LettuceConnectionFactory bean in JavaConfig.
@Bean
public LettuceConnectionFactory redisConnectionFactory() {
    RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
    redisConf.setHostName("localhost");
    redisConf.setPort(6379);
    return new LettuceConnectionFactory(redisConf);
}  
Using RedisStandaloneConfiguration we configure Redis connections via Redis connection factory.
Find the XML configuration for LettuceConnectionFactory bean.
<bean id="redisConnectionFactory" 
      class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"
      p:host-name="localhost" p:port="6379" /> 
2. Using JedisConnectionFactory
JedisConnectionFactory provides Jedis based connections. In Spring Boot 2.0, spring-boot-starter-data-redis provides Lettuce by default instead of Jedis. So to work with Jedis, we need to include Jedis dependency in our build file.
Using Maven
<dependency>
   <groupId>redis.clients</groupId>
   <artifactId>jedis</artifactId>
</dependency>  
Using Gradle
compile 'redis.clients:jedis:2.9.0'  
To get Jedis connections, we need to create JedisConnectionFactory bean in our JavaConfig.
@Bean
public JedisConnectionFactory redisConnectionFactory() {
    RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
    redisConf.setHostName("localhost");
    redisConf.setPort(6379);	    
    return new JedisConnectionFactory(redisConf);
} 
Find the XML configuration for JedisConnectionFactory bean.
<bean id="redisConnectionFactory" 
      class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory"
      p:host-name="localhost" p:port="6379" /> 

3. RedisCacheManager

RedisCacheManager is the CacheManager backed by Redis. It is instantiated using RedisCacheManager.create() or RedisCacheManager.builder() by passing connection factory. To use it we need to create RedisCacheManager bean in our JavaConfig.
@Bean
public RedisCacheManager cacheManager() {
    RedisCacheManager rcm = RedisCacheManager.create(redisConnectionFactory());
    rcm.setTransactionAware(true);
    return rcm;
} 
setTransactionAware method decides whether cache objects should be transaction-aware or not. The default value is false and when we set setTransactionAware(true), then cache put and evict operations are synchronized with ongoing Spring managed transactions. It means cache manager will put or evict caches only after commit of successful transactions.
Find the XML configuration for RedisCacheManager bean.
<bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" 
      factory-method="create" c:connection-factory-ref="redisConnectionFactory" 
      p:transaction-aware="true"/> 

4. Enable Caching

To enable cache abstraction in our application, Spring provides @EnableCaching annotation. @EnableCaching enables annotation-driven cache management capability. It is equivalent to XML <cache:annotation-driven/>. They are responsible to register required Spring components to enable annotation-driven cache management. @EnableCaching is annotated with @Configuration. Find the JavaConfig for Redis configuration annotated with @EnableCaching.
RedisConfig.java
@Configuration
@EnableCaching
@PropertySource("classpath:redis.properties")
public class RedisConfig {
   @Autowired
   private Environment env;	
	
   @Bean
   public LettuceConnectionFactory redisConnectionFactory() {
	RedisStandaloneConfiguration redisConf = new RedisStandaloneConfiguration();
	redisConf.setHostName(env.getProperty("redis.host"));
	redisConf.setPort(Integer.parseInt(env.getProperty("redis.port")));
	redisConf.setPassword(RedisPassword.of(env.getProperty("redis.password")));	    
        return new LettuceConnectionFactory(redisConf);
   }
   @Bean
   public RedisCacheManager cacheManager() {
	RedisCacheManager rcm = RedisCacheManager.create(redisConnectionFactory());
	rcm.setTransactionAware(true);
   	return rcm;
   }  
} 
Find the XML configuration for Redis using <cache:annotation-driven/>.
redis-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:p="http://www.springframework.org/schema/p"
  xmlns:c="http://www.springframework.org/schema/c"
  xmlns:context="http://www.springframework.org/schema/context"  
  xmlns:cache="http://www.springframework.org/schema/cache"  
  xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context.xsd  
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache.xsd">

    <cache:annotation-driven/>
    <context:property-placeholder location="classpath:redis.properties" ignore-unresolvable="true"/>
       
    <bean id="redisConnectionFactory" 
       class="org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory"
       p:host-name="${redis.host}" p:port="${redis.port}" p:password="${redis.password}" />
    
    <bean id="cacheManager" class="org.springframework.data.redis.cache.RedisCacheManager" 
       factory-method="create" c:connection-factory-ref="redisConnectionFactory" 
       p:transaction-aware="true"/>
</beans> 

5. Creating Cache

Find the code to perform caching.
ArticleService.java
@Service
public class ArticleService implements IArticleService {
	@Autowired
	private ArticleRepository articleRepository;
	
	@Override	
	@Cacheable(value= "articleCache", key= "#articleId")		
	public Article getArticleById(long articleId) {
		System.out.println("--- Inside getArticleById() ---");		
		return  articleRepository.findById(articleId).get();
	}
	@Override	
	@Cacheable(value= "allArticlesCache", unless= "#result.size() == 0")	
	public List<Article> getAllArticles(){
		System.out.println("--- Inside getAllArticles() ---");
		List<Article> list = new ArrayList<>();
		articleRepository.findAll().forEach(e -> list.add(e));
		return list;
	}
	@Override	
	@Caching(
		put= { @CachePut(value= "articleCache", key= "#article.articleId") },
		evict= { @CacheEvict(value= "allArticlesCache", allEntries= true) }
	)
	public Article addArticle(Article article){
		System.out.println("--- Inside addArticle() ---");		
		return articleRepository.save(article);
	}
	@Override	
	@Caching(
		put= { @CachePut(value= "articleCache", key= "#article.articleId") },
		evict= { @CacheEvict(value= "allArticlesCache", allEntries= true) }
	)
	public Article updateArticle(Article article) {
		System.out.println("--- Inside updateArticle() ---");		
		return articleRepository.save(article);
	}
	@Override	
	@Caching(
		evict= { 
			@CacheEvict(value= "articleCache", key= "#articleId"),
			@CacheEvict(value= "allArticlesCache", allEntries= true)
		}
	)
	public void deleteArticle(long articleId) {
		System.out.println("--- Inside deleteArticle() ---");		
		articleRepository.delete(articleRepository.findById(articleId).get());
	}
} 

6. Reference

Spring Data Redis

Download Source Code

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us