以下是 Spring Boot 集成 Redis 对哈希数据的详细操作示例,涵盖不同结构类型(基础类型、对象、嵌套结构)的完整代码及注释:
1. 集成步骤
1.1 添加依赖
在 pom.xml
中添加以下依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>io.lettuce</groupId>
<artifactId>lettuce-core</artifactId>
</dependency>
1.2 配置 Redis 参数
在 application.properties
中配置 Redis 服务器信息:
spring.redis.host=localhost
spring.redis.port=6379
spring.redis.password=
spring.redis.database=0
spring.redis.lettuce.pool.max-idle=8
spring.redis.lettuce.pool.max-total=8
1.3 自定义 RedisTemplate(支持对象序列化)
配置序列化器以支持复杂对象存储(如 JSON):
@Configuration
public class RedisConfig {
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
// 设置键和值的序列化器
template.setKeySerializer(new StringRedisSerializer());
template.setValueSerializer(new GenericJackson2JsonRedisSerializer());
template.setHashKeySerializer(new StringRedisSerializer());
template.setHashValueSerializer(new GenericJackson2JsonRedisSerializer());
template.afterPropertiesSet();
return template;
}
}
2. 哈希数据操作示例
2.1 存储基础类型(字符串、数字)
场景:存储用户的基本信息(如姓名、年龄)
代码示例:
@Service
public class RedisHashService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 存储基础类型数据
public void storeSimpleHashData() {
String key = "user:1001";
redisTemplate.opsForHash().put(key, "name", "Alice"); // 存储字符串
redisTemplate.opsForHash().put(key, "age", 30); // 存储数字
redisTemplate.opsForHash().put(key, "active", true); // 存储布尔值
}
// 获取哈希字段值
public void getSimpleHashData() {
String key = "user:1001";
Object name = redisTemplate.opsForHash().get(key, "name"); // 输出 "Alice"
Object age = redisTemplate.opsForHash().get(key, "age"); // 输出 30
}
// 删除字段
public void deleteHashField() {
String key = "user:1001";
redisTemplate.opsForHash().delete(key, "age"); // 删除 "age" 字段
}
}
2.2 存储对象(如 Java 对象)
场景:将 Java 对象的属性拆分为哈希字段
步骤:
- 定义实体类:
@Data
public class User {
private String name;
private int age;
private boolean active;
}
- 存储对象的属性到哈希字段:
@Service
public class RedisHashService {
// 存储对象到哈希(自动拆分属性为字段)
public void storeObjectHashData() {
String key = "user:1002";
User user = new User("Bob", 25, true);
// 将对象的属性存储为哈希字段
redisTemplate.opsForHash().putAll(key, user);
// 等效于:
// redisTemplate.opsForHash().put(key, "name", user.getName());
// redisTemplate.opsForHash().put(key, "age", user.getAge());
}
// 获取单个字段
public void getObjectField() {
String key = "user:1002";
Object age = redisTemplate.opsForHash().get(key, "age"); // 输出 25
}
// 获取所有字段
public void getAllFields() {
String key = "user:1002";
Map<Object, Object> fields = redisTemplate.opsForHash().entries(key);
// 输出:{name=Bob, age=25, active=true}
}
}
2.3 嵌套结构存储(如对象的子属性)
场景:存储嵌套对象(如用户地址信息)
步骤:
- 定义嵌套对象:
@Data
public class Address {
private String city;
private String zipcode;
}
@Data
public class UserWithAddress {
private String name;
private int age;
private Address address;
}
- 存储嵌套对象到哈希:
@Service
public class RedisHashService {
// 存储嵌套对象到哈希
public void storeNestedHashData() {
String key = "user:1003";
UserWithAddress user = new UserWithAddress();
user.setName("Charlie");
user.setAge(28);
user.setAddress(new Address("New York", "10001"));
// 使用 JSON 序列化存储整个对象到哈希的 "profile" 字段
redisTemplate.opsForHash().put(key, "profile", user);
}
// 获取嵌套对象
public void getNestedHashData() {
String key = "user:1003";
Object profile = redisTemplate.opsForHash().get(key, "profile");
UserWithAddress user = (UserWithAddress) profile;
System.out.println(user.getAddress().getCity()); // 输出 "New York"
}
}
2.4 批量操作
场景:批量设置、获取或删除哈希字段
代码示例:
@Service
public class RedisHashService {
// 批量设置字段
public void batchSet() {
String key = "user:1004";
Map<String, Object> fields = new HashMap<>();
fields.put("name", "David");
fields.put("age", 35);
redisTemplate.opsForHash().putAll(key, fields);
}
// 批量获取字段
public void batchGet() {
String key = "user:1004";
List<Object> values = redisTemplate.opsForHash().multiGet(key, Arrays.asList("name", "age"));
// 输出:["David", 35]
}
// 删除多个字段
public void batchDelete() {
String key = "user:1004";
redisTemplate.opsForHash().delete(key, "age", "active");
}
}
2.5 条件更新
场景:仅在字段存在/不存在时更新
代码示例:
@Service
public class RedisHashService {
// 仅在字段不存在时设置
public void setIfAbsent() {
String key = "user:1005";
redisTemplate.opsForHash().putIfAbsent(key, "name", "Eve"); // 成功设置
redisTemplate.opsForHash().putIfAbsent(key, "name", "Frank"); // 不会覆盖
}
// 原子性递增/递减
public void incrementField() {
String key = "user:1005";
redisTemplate.opsForHash().increment(key, "age", 1); // 若 age 不存在,初始值为1
}
}
3. 总结表格
操作类型 | 功能 | Spring Boot 方法 | 代码示例 |
---|---|---|---|
存储单个字段 | 存储键值对到哈希 | opsForHash().put(key, field, value) |
put("user:1001", "name", "Alice"); |
存储多个字段 | 批量存储字段 | opsForHash().putAll(key, map) |
putAll("user:1002", {"age":30, "active":true}); |
获取单个字段 | 获取指定字段值 | opsForHash().get(key, field) |
get("user:1001", "age"); |
获取所有字段 | 获取哈希下所有字段 | opsForHash().entries(key) |
entries("user:1001"); |
删除字段 | 删除指定字段 | opsForHash().delete(key, field) |
delete("user:1001", "age"); |
条件设置 | 仅在字段不存在时设置 | opsForHash().putIfAbsent(key, field, value) |
putIfAbsent("user:1001", "name", "Bob"); |
原子性计算 | 字段值递增/递减 | opsForHash().increment(key, field, delta) |
increment("user:1001", "score", 5); |
关键点总结
- 序列化配置:通过
GenericJackson2JsonRedisSerializer
支持复杂对象的序列化。 - 哈希操作:通过
RedisTemplate.opsForHash()
实现字段级操作。 - 嵌套结构:将对象序列化为 JSON 存储到单个哈希字段中,或拆分为多个字段。
- 批量操作:使用
putAll
、multiGet
、delete
等方法提升效率。 - 原子性操作:通过
increment
实现无锁计数,putIfAbsent
实现条件存储。
通过以上示例,可以灵活操作 Redis 哈希类型,满足不同场景下的数据存储和计算需求。