Backend Development 8 min read

Mastering Spring Data Redis Repositories: CRUD, Indexing, and TTL

Learn how to seamlessly integrate Spring Data Redis Repositories in a Spring Boot 2.7 environment, covering object mapping, CRUD operations, indexing with @Indexed, query‑by‑example, batch saves, and setting expiration using @TimeToLive, complete with code examples and visual data representations.

Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Spring Full-Stack Practical Cases
Mastering Spring Data Redis Repositories: CRUD, Indexing, and TTL

1. Introduction

Environment: Spring Boot 2.7.16.

Spring Data Redis Repositories allow seamless conversion and storage of domain objects in Redis hashes, support custom mapping strategies, and provide auxiliary indexes.

Redis Repositories require Redis Server version 2.8.0 or higher and do not support transactions. Ensure that the RedisTemplate has transaction support disabled.

<code>StringRedisTemplate template = new StringRedisTemplate(redisConnectionFactory);
template.setEnableTransactionSupport(false);</code>

Typical hash operations:

<code>@Resource
private StringRedisTemplate stringRedisTemplate;

public void save1(Person person) {
  // Method 1
  this.stringRedisTemplate.opsForHash().put("persons:1", "age", "20");
  this.stringRedisTemplate.opsForHash().put("persons:1", "name", "张三");
  // Method 2
  Map<String, String> datas = new HashMap<>();
  datas.put("age", "20");
  datas.put("name", "张三");
  this.stringRedisTemplate.opsForHash().putAll("persons:1", datas);
}</code>

While these operations work, storing a complete object is cumbersome and querying by a specific field is difficult. Spring Data Redis offers an object‑oriented approach to handle hash structures, supporting complex operations.

2. Practical Example

Define Entity

<code>@RedisHash(value = "persons")
public class Person {
  @Id
  private Long id;
  private String name;
  private String sex;
  private Integer age;
  private Date birthday;
}</code>

The @RedisHash annotation and the @Id field create the actual key for persisting the hash. Next, define a repository for CRUD operations.

<code>public interface PersonRepository extends CrudRepository<Person, Long> {
}
</code>

The PersonRepository inherits basic CRUD methods.

Service Layer

<code>@Service
public class PersonService {
  @Resource
  private StringRedisTemplate stringRedisTemplate;
  @Resource
  private PersonRepository personRepository;

  // Save a single entity
  public void save(Person person) {
    this.personRepository.save(person);
  }

  // Batch save
  public void save(List<Person> persons) {
    this.personRepository.saveAll(persons);
  }

  // Update entity
  public void update(Person person) {
    this.personRepository.save(person);
  }

  // Find by ID
  public Person queryById(Long id) {
    return this.personRepository.findById(id).orElse(null);
  }

  // Delete by ID
  public void removeById(Long id) {
    this.personRepository.deleteById(id);
  }
}
</code>

Unit Tests – Save Operation

<code>@Resource
private PersonService ps;

@Test
public void testSave() {
  Person person = new Person(1L, "张三", "男", 33, new Date());
  this.ps.save(person);
}
</code>

After saving, Redis stores two keys: a SET for primary keys and a HASH for the Person fields. The HASH includes a _class attribute holding the fully qualified class name.

Query Operation

<code>@Test
public void testQuery() {
  System.out.println(this.ps.queryById(1L));
}
</code>
<code>Person [id=1, name=张三, sex=男, age=33, birthday=Wed Feb 07 14:56:24 GMT+08:00 2024]
</code>

To query by name, add the @Indexed annotation to the field.

<code>public class Person {
  @Indexed
  private String name;
}
</code>

After re‑adding data, an index key is created for the name field, mapping to the entity ID. Queries are performed using Query‑by‑Example (QBE):

<code>public Iterable<Person> qbe(Person person) {
  return this.personRepository.findAll(Example.of(person));
}
</code>
<code>@Test
public void testQbe() {
  Person person = new Person();
  person.setName("张三");
  this.ps.qbe(person).forEach(System.out::println);
}
</code>

Console output shows the correct entity when @Indexed is present.

Setting Expiration (TTL)

Two approaches can set a time‑to‑live:

Add an extra field with @TimeToLive annotation.

<code>@TimeToLive
private Long expiration;
</code>

When saving, assign the expiration value in seconds.

<code>@Test
public void testSave() {
  Person person = new Person(1L, "张三", "男", 33, new Date());
  person.setExpiration(200L);
  this.ps.save(person);
}
</code>

Alternatively, define TTL directly on the @RedisHash annotation:

<code>@RedisHash(value = "persons", timeToLive = 30000)
public class Person {
}
</code>

This sets a uniform expiration for all instances of the entity.

All the above demonstrates how to use Spring Data Redis Repositories for object mapping, CRUD, indexing, query‑by‑example, and TTL management in a Spring Boot application.

Hope this article helps you.

IndexingRedisSpring BootTTLCRUDSpring Data
Spring Full-Stack Practical Cases
Written by

Spring Full-Stack Practical Cases

Full-stack Java development with Vue 2/3 front-end suite; hands-on examples and source code analysis for Spring, Spring Boot 2/3, and Spring Cloud.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.