Working with Redis Database Using Spring Boot

Working with Redis Database Using Spring Boot | Redis is open-source software that can be used as an In-Memory Database. We can also use it as a cache manager or Message Broker i.e. sending continuous data between two different applications. Redis is mostly used as a cache manager as compared to the database, but to understand how the cache manager works in Spring boot we should have basic knowledge of Redis database operations using Spring boot. Also see:- Spring Boot With Redis Cache Example.

Redis isn’t like MySQL or PlSQL databases, it is a plain database. Here we will get some memory, and in that memory, we are going to perform some operations like storing the data, retrieving the data, and all. We can compare it with NoSQL databases. We have to write NoSQL queries for it.

  • It is like Empty Memory.
  • No SQL, No Tables, No Sequence, No Joins, and e.t.c.
  • The data can be stored in Java String, List, or Set formats. Or we can perform HashOperation. In these HashOperation is mostly used.
  • It has in-built services for transaction management and memory cleaning.

To work with Redis first we need to download and install redis-server in our system, after that we can use it using Spring Boot. The default port for Redis is 6379. To check redis-server version in Ubuntu:-

$ redis-server -v

Dependency Required to Work with Redis

To work with the Redis database “Spring Data Redis (Access+Driver)” dependency is required. It will add the following entry in the Maven pom.xml file:-

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

To communicate with Redis above dependency contains two drivers:- jedis, and lettuce. We can use one of these drivers which needed to be configured in our Spring boot project. The lettuce is the latest driver, and it also provides better performance compared to jedis driver. After loading the driver, the connection can be created and we can communicate with the Redis database.

Redis is mostly used as a cache manager as compared to the database. But to understand how internally it works first we are going to see the database and later cache manager. It will highly concentrate on the cache manager concept only which reduces network calls between application and database.

How to Create a Connection With Redis

To create a connection between the application and Redis we need to use the RedisConnectionFactory interface which has two implementation classes:- JedisConnectionFactory & LettuceConnectionFactory.

package com.knowprogram.demo.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;

@Configuration
public class AppConfig {
    
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }
}

LettuceConnectionFactory needs some input to create the connection like port number, host information, and e.t.c. In the application.properties file:-

## Redis key-val (props)
spring.redis.host=localhost
spring.redis.port=6379

To perform the operations RedisTemplate class is provided which will reduce our work & directly we can perform the operations. ConnectionFactory details are needed to pass to the RedisTemplate. The RedisTemplate supports different HashOperations.

Spring Boot Example Application – Redis as Database

Step-1. Create one Spring Boot Starter Project.

Add “Lombok” and “Spring Data Redis (Access+Driver)” dependencies. See this application code at GitHub:- RedisAsDBSpringBoot

Step-2. In application.properties

spring.redis.host=localhost
spring.redis.port=6379

Step-3. Create Model class.

The model class must be Serializable.

package com.knowprogram.demo.model;

import java.io.Serializable;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student implements Serializable {
    
    private static final long serialVersionUID = 1L;
    private Integer stdId;
    private String stdName;
    private Double stdFee;
}

Step-4. Create Redis Connection & Template

In the Spring Config file create the followings:-

  • Redis Connection
  • Redis Template
package com.knowprogram.demo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

import com.knowprogram.demo.model.Student;

@Configuration
public class AppConfig {

    // 1. Redis Connection
    @Bean
    public RedisConnectionFactory redisConnectionFactory() {
        return new LettuceConnectionFactory();
    }

    // 2. Redis Template
    @Bean
    public RedisTemplate<String, Student> redisTemplate() {
        RedisTemplate<String, Student> template = new RedisTemplate<>();
        template.setConnectionFactory(redisConnectionFactory());
        return template;
    }
}

Step-5. Define one interface.

package com.knowprogram.demo.dao;

import java.util.Map;

import com.knowprogram.demo.model.Student;

public interface IStudentDao {
    
    void addStudent(Student s);
    void modifyStudent(Student s);
    Student getOneStudent(Integer id); 
    Map<Integer, Student> getAllStudent();
    void removeStudent(Integer id);
}

Step-6. Define the Implementation class for the above interface.

Create StudentDaoImpl Using HashOperations<H, HK, HV>. Where:-

  • H (Href) = String (‘STUDENT’)
  • HK (Key) = Integer (stdId)
  • HV (Val) = Object Type
package com.knowprogram.demo.dao.impl;

import java.util.Map;

import org.springframework.data.redis.core.HashOperations;
import org.springframework.stereotype.Repository;

import com.knowprogram.demo.dao.IStudentDao;
import com.knowprogram.demo.model.Student;

import jakarta.annotation.Resource;

@Repository
public class StudentDaoImpl implements IStudentDao {

    private final String KEY = "STUDENT";

    // inject template from AppConfig
    @Resource(name = "redisTemplate")
    private HashOperations<String, Integer, Student> operation;

    @Override
    public void addStudent(Student s) {
        // create new record in HashMemory if given id not exist
        operation.putIfAbsent(KEY, s.getStdId(), s);
    }

    @Override
    public void modifyStudent(Student s) {
        // update data with given id
        operation.put(KEY, s.getStdId(), s);
    }

    @Override
    public Student getOneStudent(Integer id) {
        // read one record based on HashRed and Id
        return operation.get(KEY, id);
    }

    @Override
    public Map<Integer, Student> getAllStudent() {
        // hash Ref, get all rows as Map
        return operation.entries(KEY);
    }

    @Override
    public void removeStudent(Integer id) {
        // Hash Red, key
        operation.delete(KEY, id);
    }

}

Step-7. Test Operations

For testing, we will use CommandLineRunner, but you can also use RestController. If the class implements CommandLineRunner and has @Component then those classes will be executed at the time of the start of the application.

package com.knowprogram.demo.runner;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import com.knowprogram.demo.dao.IStudentDao;
import com.knowprogram.demo.model.Student;

@Component
public class RedisOperationTest implements CommandLineRunner {

    @Autowired
    private IStudentDao dao;

    @Override
    public void run(String... args) throws Exception {
        dao.addStudent(new Student(101, "Amelia", 500.25));
        dao.addStudent(new Student(102, "William", 800.25));
        dao.addStudent(new Student(103, "Jerry", 600.25));

        System.out.println("All Rows: ");
        dao.getAllStudent().forEach((k, v) -> System.out.println(k + " - " + v));

        dao.removeStudent(101);
        dao.modifyStudent(new Student(103, "Tom", 650.25));
        
        System.out.println("After remove/modify: ");
        dao.getAllStudent().forEach((k, v) -> System.out.println(k + " - " + v));
    }

}

Step-8. Run the application.

  • Start the Redis server.
  • Run Spring boot application.

Output:-

All Rows:
101 – Student(stdId=101, stdName=SAM, stdFee=500.25)
102 – Student(stdId=102, stdName=SYED, stdFee=800.25)
103 – Student(stdId=103, stdName=RAM, stdFee=600.25)
After remove/modify:
102 – Student(stdId=102, stdName=SYED, stdFee=800.25)
103 – Student(stdId=103, stdName=Tom, stdFee=650.25)

At the time of cache Management, we are not going to write all these codes. Instead, these codes will be handled by Spring Boot itself. Also see:- Junit & Mockito With Spring Boot Rest Application

If you enjoyed this post, share it with your friends. Do you want to share more information about the topic discussed above or do you find anything incorrect? Let us know in the comments. Thank you!

Leave a Comment

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