spring

Spring Data Redis Example

Redis is an in-memory key/value store. It is used as a database, cache and message broker. In this article, we will see some examples of Spring Data Redis. Before we get to start with the examples, we need to first install Redis and configure the server.

1. Overview of Redis

Redis is an extremely high-performance, lightweight key/value based data store. It provides several operations like persistenting byte arrays, lists, sets, and hash data structures. It also supports a way to generate atomic counters and also has an efficient topic-based pub/sub messaging functionality. It lacks in complex querying functionality. Redis servers can also be clustered together to povide distributed environment. One can interact with Redis using command line.

2. Installing Redis

  1. Download Redis Release. We have downloaded the release for Windows 3.0 on 64 bit.
  2. Download the binaries, bundled as zip file and the installer MSI file.
  3. Unzip the binaries to a new directory, for example, c:\redis. Copy the installer to the same directory.
  4. Run the installer file and follow through the wizard.
  5. Once installed, redis is available as service. By default it will already be started.

3. Start Redis Manually

In case you want to start redis manually. Stop the redis service, go to the installed redis directory and run redis-server.exe from command line.

C:\redis<redis-server.exe
[5784] 06 Jan 08:46:59.903 # Warning: no config file specified, using the defaul
t config. In order to specify a config file use redis-server.exe /path/to/redis.
conf
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 3.0.500 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 5784
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

[5784] 06 Jan 08:46:59.920 # Server started, Redis version 3.0.500
[5784] 06 Jan 08:46:59.921 * The server is now ready to accept connections on po
rt 6379

4. Accessing Redis using command line

Now that we have started the server, its good time to quickly test redis. Maybe insert a key/value and retrieve it.
In order to quickly test, you can use Redis command-line shell that you can use interactively.

  1. Go to the installed redis directory and then run redis-cli from command line.
    C:\redis<redis-cli
    127.0.0.1:6379<
    
  2. Get all the keys.
    127.0.0.1:6379< keys *
    (empty list or set)
    127.0.0.1:6379>
    
  3. Insert a key value.
    127.0.0.1:6379< set example spring-redis
    OK
    
  4. Get all the keys.
    127.0.0.1:6379< keys *
    1) "example"
    127.0.0.1:6379>
    
  5. Let’s now get value of “example”.
    127.0.0.1:6379< get example
    "spring-redis"
    

5. Accessing Redis using Java

In order to connect to Redis using java, you need to first download a redis driver. You can see the redis java drives listed here. In our examples, we will use Jedis.

Add the following dependency to your pom.xml.

pom.xml:

<dependency>
	<groupId>redis.clients</groupId>
	<artifactId>jedis</artifactId>
	<version>2.8.0</version>
</dependency>

6. Dependencies

Since we want to use spring support for accessing redis, you also need to add spring based artifacts to pom.xml.
Here is the complete pom.xml.

  1. spring-data-redis is for the spring-redis support.
  2. spring-core and spring-context for spring bean and context support.
  3. commons-pool2 – Apache commons pool
  4. jedis – Redis Java Driver

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacodegeeks.spring.redis</groupId>
	<artifactId>springQuartzScheduler</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>4.1.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>4.1.5.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-redis</artifactId>
			<version>1.5.0.RELEASE</version>
		</dependency>
		<dependency>
			<groupId>org.apache.commons</groupId>
			<artifactId>commons-pool2</artifactId>
			<version>2.4.2</version>
		</dependency>
		<dependency>
			<groupId>redis.clients</groupId>
			<artifactId>jedis</artifactId>
			<version>2.8.0</version>
		</dependency>

	</dependencies>
</project>

7. Spring Redis Configuration

To connect to Redis using Jedis, you need to create an instance of org.springframework.data.redis.connection.jedis.JedisConnectionFactory.

The other driver libraries have corresponding ConnectionFactory subclasses.

SpringRedisConfig:

package com.javacodegeeks.spring.redis;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;

@Configuration
public class SpringRedisConfig {
	@Bean
	public JedisConnectionFactory connectionFactory() {
		JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
		connectionFactory.setHostName("localhost");
		connectionFactory.setPort(6379);
		return connectionFactory;
	}
}

8. RedisTemplate Example

Just the way spring provides template classes, even for redis, spring provides RedisTemplate to simplify Redis data access code.

SpringRedisConfig:

package com.javacodegeeks.spring.redis;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;

@Configuration
public class SpringRedisConfig {
	@Bean
	public JedisConnectionFactory connectionFactory() {
		JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
		connectionFactory.setHostName("localhost");
		connectionFactory.setPort(6379);
		return connectionFactory;
	}

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

It performs automatic serialization/deserialization between the given objects and the underlying binary data in the Redis store. By default, it uses Java serialization for its objects.

9. Set and Get Object using Redis ValueOperations

Redis deals directly with byte arrays and doesn’t natively perform Object to byte[] translation. By default spring uses Java serialization. In the below example, we want to store Employee object as it is and retrieve it later.

Employee:

package com.javacodegeeks.spring.redis;

import java.io.Serializable;

public class Employee implements Serializable {
	private static final long serialVersionUID = 1L;
	private String id;
	private String name;
	private Integer age;

	public Employee(){}
	
	public Employee(String id, String name) {
		this.id = id;
		this.name = name;
	}
	
	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String toString() {
		return "Employee [" + getId() + ", " + getName() + "]";
	}
}

Since Redis supports various operations like list operations, set operations, value operations etc, it provides sub-interfaces to deal with each use case. Since we want to set and get values, we’ll be using the ValueOperations template which we will be getting using RedisTemplate.opsForValue().

SpringRedisExample:

package com.javacodegeeks.spring.redis;

import java.net.URISyntaxException;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

public class SpringRedisExample {
	public static void main(String[] args) throws URISyntaxException, Exception {
		ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
				SpringRedisConfig.class);
		try {			
			RedisTemplate redisTemplate = (RedisTemplate) ctx.getBean("redisTemplate");
			ValueOperations values = redisTemplate.opsForValue();
			values.set("joe", new Employee("01", "Joe"));
			
			System.out.println("Employee added: " + values.get("joe"));
		} finally {
			ctx.close();
		}
	}
}

Output:

Jan 06, 2016 11:10:01 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6576fe71: startup date [Wed Jan 06 11:10:01 IST 2016]; root of context hierarchy
Employee added: Employee [01, Joe]
Jan 06, 2016 11:10:01 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6576fe71: startup date [Wed Jan 06 11:10:01 IST 2016]; root of context hierarchy

10. StringRedisTemplate Example

If you’re going to be dealing largely with Strings, the it is better to use the specific template class StringRedisTemplate.
Let’s modify the config class. Add strRedisTemplate() to it to return StringRedisTemplate object.

SpringRedisConfig:

package com.javacodegeeks.spring.redis;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class SpringRedisConfig {
	@Bean
	public JedisConnectionFactory connectionFactory() {
		JedisConnectionFactory connectionFactory = new JedisConnectionFactory();
		connectionFactory.setHostName("localhost");
		connectionFactory.setPort(6379);
		return connectionFactory;
	}

	@Bean
	public RedisTemplate redisTemplate() {
		RedisTemplate redisTemplate = new RedisTemplate();
		redisTemplate.setKeySerializer(new StringRedisSerializer());
		redisTemplate.setConnectionFactory(connectionFactory());
		return redisTemplate;
	}
	
	@Bean
	public StringRedisTemplate strRedisTemplate() {
		StringRedisTemplate redisTemplate = new StringRedisTemplate();
		redisTemplate.setConnectionFactory(connectionFactory());
		return redisTemplate;
	}
}

SpringStringRedisExample:

package com.javacodegeeks.spring.redis;

import java.net.URISyntaxException;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

public class SpringStringRedisExample {
	public static void main(String[] args) throws URISyntaxException, Exception {
		ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
				SpringRedisConfig.class);
		try {			
			StringRedisTemplate redisTemplate = (StringRedisTemplate) ctx.getBean("strRedisTemplate");
			ValueOperations values = redisTemplate.opsForValue();
			values.set("01", "Joe");
			values.set("02", "John");
			
			System.out.println("Employee added: " + values.get("01"));
			System.out.println("Employee added: " + values.get("02"));
		} finally {
			ctx.close();
		}
	}
}

Output:

Jan 06, 2016 11:21:22 AM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6576fe71: startup date [Wed Jan 06 11:21:22 IST 2016]; root of context hierarchy
Employee added: Joe
Employee added: John
Jan 06, 2016 11:21:23 AM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6576fe71: startup date [Wed Jan 06 11:21:22 IST 2016]; root of context hierarchy

11. Redis Hash Operations Example

In this example, we will use the Redis hash operations to store a map of attributes against a hash key. These attributes might be properties of a POJO class. This way we can store retrieves related properties with ease. Call RedisTemplate.opsForHash() to get the hash operations object.

SpringRedisHashExample:

package com.javacodegeeks.spring.redis;

import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;

public class SpringRedisHashExample {
	public static void main(String[] args) throws URISyntaxException, Exception {
		ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
				SpringRedisConfig.class);
		try {			
			StringRedisTemplate redisTemplate = (StringRedisTemplate) ctx.getBean("strRedisTemplate");
			HashOperations<String, String, String> hash = redisTemplate.opsForHash();
			String empJoeKey = "emp:joe";
			String empJohnKey = "emp:john";
			
			Map<String, String> empJoeMap = new HashMap<>();
			empJoeMap.put("name", "Joe");
			empJoeMap.put("age", "32");
			empJoeMap.put("id", "01");
			
			Map<String, String> empJohnMap = new HashMap<>();
			empJohnMap.put("name", "John");
			empJohnMap.put("age", "42");
			empJohnMap.put("id", "02");
			
			hash.putAll(empJoeKey, empJoeMap);
			hash.putAll(empJohnKey, empJohnMap);	
			
			System.out.println("Get emp joe details: " + hash.entries(empJoeKey));
			System.out.println("Get emp john details: " + hash.entries(empJohnKey));
		} finally {
			ctx.close();
		}
	}
}

Output:

Jan 06, 2016 12:24:03 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@6576fe71: startup date [Wed Jan 06 12:24:03 IST 2016]; root of context hierarchy
Get emp joe details: {id=01, age=32, name=Joe}
Get emp john details: {age=42, name=John, id=02}
Jan 06, 2016 12:24:03 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6576fe71: startup date [Wed Jan 06 12:24:03 IST 2016]; root of context hierarchy

12. Redis AtomicLong Example

In case of distributed application, there may be scenarios where we need a unique number which is unique across the applications in cluster. Spring Data Redis uses the value operations internally to manage the atomic numbers like AtomicInteger, AtomicLong and backs the current by a Redis instance. This way we can always generate a unique number irrespective of the JVM. In thebelow example, we use instance of RedisAtomicLong to get the current long number set against a key and increment it atomically.

SpringRedisAtomicLongExample:

package com.javacodegeeks.spring.redis;

import java.net.URISyntaxException;

import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;

public class SpringRedisAtomicLongExample {
	public static void main(String[] args) throws URISyntaxException, Exception {
		ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext(
				SpringRedisConfig.class);
		try {			
			RedisConnectionFactory connectionFactory = (RedisConnectionFactory) ctx.getBean("connectionFactory");
			RedisAtomicLong uniqueNbr =
					new RedisAtomicLong("RedisUniqueNbr", connectionFactory, 0);
			System.out.println("Redis Atomic Long: " + uniqueNbr.incrementAndGet());
			
		} finally {
			ctx.close();
		}
	}
}

Output:

Jan 06, 2016 2:21:50 PM org.springframework.context.annotation.AnnotationConfigApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@45c8e616: startup date [Wed Jan 06 14:21:50 IST 2016]; root of context hierarchy
Redis Atomic Long: 1
Jan 06, 2016 2:22:27 PM org.springframework.context.annotation.AnnotationConfigApplicationContext doClose
INFO: Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@45c8e616: startup date [Wed Jan 06 14:21:50 IST 2016]; root of context hierarchy

13. Download the source code

This was an example about Spring Data Redis.

Download
You can download the full source code of this example here: springRedisExample.zip

Ram Mokkapaty

Ram holds a master's degree in Machine Design from IT B.H.U. His expertise lies in test driven development and re-factoring. He is passionate about open source technologies and actively blogs on various java and open-source technologies like spring. He works as a principal Engineer in the logistics domain.
Subscribe
Notify of
guest

This site uses Akismet to reduce spam. Learn how your comment data is processed.

4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Rui
Rui
6 years ago

Hi There,

Is there any way to expire hash entries or set a TTL to hash entries in spring data ?

Amer
Amer
4 years ago
Reply to  Rui

Did you figure this out ?

Sai praneeth Kodi
Sai praneeth Kodi
4 years ago
Reply to  Rui

Have you achieved it

Ravinath
2 months ago

How to upgrade jedis 4+ ?

Back to top button