Building a Spring Boot Application with Redis Caching for Customer CRUD Operations

D2Y MVN
4 min readOct 19, 2024

In this tutorial, we will build a simple Customer CRUD application using Spring Boot. We’ll also implement Redis caching to improve performance by reducing database queries. The project will connect to a PostgreSQL database, and we’ll also configure Elasticsearch and Kafka for future scalability.

Prerequisites:

  1. Java 11 or above
  2. PostgreSQL installed
  3. Redis installed

Project Setup:

Step 1: Initialize a Spring Boot Project

You can create a Spring Boot project using Spring Initializr or your preferred method. Here’s what you need:

  • Group: com.example
  • Artifact: customer-redis-app
  • Dependencies:
  • Spring Web
  • Spring Data JPA
  • Spring Data Redis
  • PostgreSQL Driver
  • Lombok

Once you generate the project, it will provide you with a base structure. We will modify this to include our custom logic.

Step 2: Add Dependencies to pom.xml

Open the pom.xml file and ensure the following dependencies are added:

 <dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>

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

<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>

Step 3: Configure Application Properties

In the src/main/resources/application.properties file, configure the necessary settings:

# Redis Configuration
spring.redis.host=localhost
spring.redis.port=6379

# PostgreSQL
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:5432/spring-redis
spring.datasource.username=your_username
spring.datasource.password=your_password

# Konfigurasi JPA (Hibernate)
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
#spring.jpa.properties.hibernate.format_sql=true
#spring.jpa.show-sql=true

Make sure to adjust these configurations according to your local environment.

Step 4: Create the Redis Configuration Class

To use Redis for caching, create a RedisConfig class.

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(connectionFactory);
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
return template;
}
}

Step 5: Create the Customer Entity

The Customer entity represents the data model for the application.

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.Serializable;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Entity
public class Customer implements Serializable {

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
}

Step 6: Create the Customer DTO

We use a DTO (Data Transfer Object) to transfer data between layers in a clean way.

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

@Data
@AllArgsConstructor
@NoArgsConstructor
public class CustomerDTO {
private Long id;
private String name;
private String email;
}

Step 7: Create the Customer Repository

The repository interface will handle database operations.

import org.springframework.data.jpa.repository.JpaRepository;

public interface CustomerRepository extends JpaRepository<Customer, Long> {
}

Step 8: Implement the Customer Service with Redis Caching

We will now create the service layer with Redis caching applied to the methods.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Optional;

@Service
public class CustomerService {

@Autowired
private CustomerRepository customerRepository;

@Cacheable(value = "customers", key = "#id")
public Optional<Customer> getCustomerById(Long id) {
return customerRepository.findById(id);
}

@Cacheable(value = "customers")
public List<Customer> getAllCustomers() {
return customerRepository.findAll();
}

@CachePut(value = "customers", key = "#customer.id")
public Customer createCustomer(Customer customer) {
return customerRepository.save(customer);
}

@CachePut(value = "customers", key = "#customer.id")
public Customer updateCustomer(Customer customer) {
return customerRepository.save(customer);
}

@CacheEvict(value = "customers", key = "#id")
public void deleteCustomer(Long id) {
customerRepository.deleteById(id);
}
}

Step 9: Create the Customer Controller

The controller will handle HTTP requests for the CRUD operations.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
@RequestMapping("/api/customers")
public class CustomerController {

@Autowired
private CustomerService customerService;

@GetMapping("/{id}")
public ResponseEntity<CustomerDTO> getCustomerById(@PathVariable Long id) {
return customerService.getCustomerById(id)
.map(customer -> ResponseEntity.ok(convertToDto(customer)))
.orElse(ResponseEntity.notFound().build());
}

@GetMapping
public List<CustomerDTO> getAllCustomers() {
return customerService.getAllCustomers().stream()
.map(this::convertToDto)
.toList();
}

@PostMapping
public ResponseEntity<CustomerDTO> createCustomer(@RequestBody CustomerDTO customerDTO) {
Customer customer = convertToEntity(customerDTO);
return ResponseEntity.ok(convertToDto(customerService.createCustomer(customer)));
}

@PutMapping("/{id}")
public ResponseEntity<CustomerDTO> updateCustomer(@PathVariable Long id, @RequestBody CustomerDTO customerDTO) {
Customer customer = convertToEntity(customerDTO);
customer.setId(id);
return ResponseEntity.ok(convertToDto(customerService.updateCustomer(customer)));
}

@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteCustomer(@PathVariable Long id) {
customerService.deleteCustomer(id);
return ResponseEntity.noContent().build();
}

private CustomerDTO convertToDto(Customer customer) {
CustomerDTO dto = new CustomerDTO();
dto.setId(customer.getId());
dto.setName(customer.getName());
dto.setEmail(customer.getEmail());
return dto;
}

private Customer convertToEntity(CustomerDTO dto) {
Customer customer = new Customer();
customer.setName(dto.getName());
customer.setEmail(dto.getEmail());
return customer;
}
}

Step 10: Enable Caching in Spring Boot

Finally, we need to enable caching by adding the @EnableCaching annotation in the main application class.

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class CustomerRedisAppApplication {
public static void main(String[] args) {
SpringApplication.run(CustomerRedisAppApplication.class, args);
}
}

Step 11: Running the Application

To run the application, use the following command:

mvn spring-boot:run

You’ve successfully built a Spring Boot application with Customer CRUD operations and implemented Redis caching. The caching mechanism stores data in Redis, reducing the load on the PostgreSQL database. You can further enhance this project by integrating Kafka and Elasticsearch for messaging and searching capabilities.

The complete source code for this project is available on GitHub.

Happy Coding!

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

D2Y MVN
D2Y MVN

Written by D2Y MVN

Lets make a plane and take a risk!

No responses yet

Write a response