In this tutorial, we will take a look at how to use Redis Database as a Cache for your Spring Boot Application.
In software development, caching really helps to improve the performance of the application and thus reduces the load on resources. In a Java application, caching can be used to store frequently accessed data in memory, thus making decreasing the latency of your application.
Redis is a one of the popular in-memory data store that can be used for caching in Java applications.
For this tutorial, we will use MySQL database as our primary database, we will keep the application simple so that it's easy to understand the concept of caching and the configuration.
Step 1: MySql + Redis configuration
applications.properties
#mySQL DB
spring.datasource.url=jdbc:mysql://localhost/jdbctest
spring.datasource.username=root
spring.datasource.password=
spring.jpa.hibernate.ddl-auto=update
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
#Redis as Cache
spring.cache.type=redis
spring.data.redis.url=redis://:password@redis-host.redislabs.com:port
spring.cache.redis.time-to-live=5s
Note: Again! To keep it simple I am using Redis Cloud.
Gradle Configuration
plugins {
id 'java'
id 'org.springframework.boot' version '3.0.6'
id 'io.spring.dependency-management' version '1.1.0'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-redis'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-validation'
implementation 'org.jetbrains:annotations:23.0.0'
implementation 'mysql:mysql-connector-java:8.0.14'
}
tasks.named('test') {
useJUnitPlatform()
}
Step 2: Our Entity
Keeping it really simple with an userId and userName fields.
package com.example.redisdemo;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.Id;
import java.io.Serializable;
@Entity
public class DbUser implements Serializable {
private static final long serialVersionUID = 1L;
public DbUser(int userId, String userName) {
this.userId = userId;
this.userName = userName;
}
public DbUser() {
}
@Id
private int userId;
@Column
private String userName;
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
}
Step 3: Spring JPA Repository class for DbUser
package com.example.redisdemo;
import io.lettuce.core.dynamic.annotation.Param;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;
import java.util.Optional;
@Repository
public interface DbUserRepository extends JpaRepository<DbUser,Integer> {
public Optional<DbUser> findUserByUserId(Integer userId);
public DbUser save(DbUser user);
@Modifying
@Query("update DbUser u set u.userName = :userName where u.userId = :userId")
void updateUserName(@Param("userId") Integer userId, @Param("userName") String userName);
void deleteUserByUserId(Integer userId);
}
Step 4: User Service class
package com.example.redisdemo;
import jakarta.transaction.Transactional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.stereotype.Service;
import java.util.Optional;
@Service
@EnableCaching
@CacheConfig(cacheNames = "dbUsers")
public class UserService {
@Autowired
DbUserRepository dbUserRepository;
@Cacheable(key = "#userId",value = "dbUsers")
public Optional<DbUser> findUserByUserId(Integer userId) {
System.out.println("User fetched from Db!");
return dbUserRepository.findUserByUserId(userId);
}
public DbUser save(DbUser user) {
return dbUserRepository.save(user);
}
@Transactional
@CacheEvict(key = "#userId", value = "dbUsers")
public void updateUser(Integer userId, String userName) {
dbUserRepository.updateUserName(userId,userName);
}
@Transactional
@CacheEvict(key = "#userId", value = "dbUsers")
public void deleteUserByUserId(Integer userId) {
dbUserRepository.deleteUserByUserId(userId);
}
}
Step 5: User Controller
package com.example.redisdemo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.Optional;
@RestController
public class UserController {
@Autowired
UserService userService;
@Autowired
FlushRedis flushRedis;
@GetMapping(path = "/get-user/{userId}")
public Optional<DbUser> getUserName(@PathVariable("userId") int userId) {
return userService.findUserByUserId(userId);
}
@PostMapping(path = "/add-user")
public void addUser(@RequestBody DbUser user) {
System.out.println("User Saved!");
userService.save(user);
}
@PostMapping(path = "/update-user")
public void updateUSer(@RequestBody DbUser user) {
System.out.println("User Saved!");
userService.updateUser(user.getUserId(),user.getUserName());
}
@DeleteMapping(path = "/delete-user/{userId}")
public void deleteUSer(@PathVariable("userId") int userId) {
System.out.println("User Saved!");
userService.deleteUserByUserId(userId);
}
}
As you may see we have performed all CRUD operations using Spring Data JPA + MySQL, as well as made use of Redis as Cache to be in Sync with our data.
CRUD Operations cURL Commands
Create User:
curl --location 'http://localhost:8080/add-user' \ --header 'Content-Type: application/json' \ --data '{ "userId": 10, "userName": "Harry" }'
Retrieve User:
curl --location 'curl --location 'http://localhost:8080/get-user/10' \ --header 'Content-Type: application/json''
Update User:
curl --location 'curl --location 'http://localhost:8080/update-user' \ --header 'Content-Type: application/json' \ --data '{ "userId":10, "userName":"Ron" }''
Delete User:
curl --location --request DELETE 'http://localhost:8080/delete-user/10'
You may also use clients like Postman to perform these API calls.
Facing issues? Have Questions? Post them here! I am happy to answer!
Rakesh (He/Him) has over 14+ years of experience in Web and Application development. He is the author of insightful How-To articles for Code2care.
Follow him on: X
You can also reach out to him via e-mail: rakesh@code2care.org
- Get the current timestamp in Java
- Java Stream with Multiple Filters Example
- Java SE JDBC with Prepared Statement Parameterized Select Example
- Fix: UnsupportedClassVersionError: Unsupported major.minor version 63.0
- [Fix] Java Exception with Lambda - Cannot invoke because object is null
- 7 deadly java.lang.OutOfMemoryError in Java Programming
- How to Calculate the SHA Hash Value of a File in Java
- Java JDBC Connection with Database using SSL (https) URL
- How to Add/Subtract Days to the Current Date in Java
- Create Nested Directories using Java Code
- Spring Boot: JDBCTemplate BatchUpdate Update Query Example
- What is CA FE BA BE 00 00 00 3D in Java Class Bytecode
- Save Java Object as JSON file using Jackson Library
- Adding Custom ASCII Text Banner in Spring Boot Application
- [Fix] Java: Type argument cannot be of primitive type generics
- List of New Features in Java 11 (JEPs)
- Java: How to Add two Maps with example
- Java JDBC Transition Management using PreparedStatement Examples
- Understanding and Handling NullPointerException in Java: Tips and Tricks for Effective Debugging
- Steps of working with Stored Procedures using JDBCTemplate Spring Boot
- Java 8 java.util.Function and BiFunction Examples
- The Motivation Behind Generics in Java Programming
- Get Current Local Date and Time using Java 8 DateTime API
- Java: Convert Char to ASCII
- Deep Dive: Why avoid java.util.Date and Calendar Classes
- Find Nearest Gas Station using Google Map App on your Phone - Google
- Fix: ValueError: operands could not be broadcast together with shapes [Python numpy] - Python
- Fix: AssertionError in Python - Python
- Encode or Decode Base64 String using Mac Terminal Command - MacOS
- [Solved] SharePoint Illegal operation attempted on a registry key that has been marked for deletion - SharePoint
- Update Powershell Using Command Line - Powershell
- How to install python pip on Ubuntu using apt command - Linux
- Fix - sudo: systemctl: command not found - Ubuntu