本文目录导读:

下面我来详细介绍Java操作Redis哈希(Hash)的读写案例,包括Jedis和Spring Data Redis两种主流方式。
使用Jedis操作Redis Hash
添加依赖
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>5.0.0</version>
</dependency>
完整案例代码
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;
import java.util.HashMap;
import java.util.Map;
public class RedisHashExample {
private static JedisPool jedisPool;
static {
// 创建连接池配置
JedisPoolConfig poolConfig = new JedisPoolConfig();
poolConfig.setMaxTotal(10);
poolConfig.setMaxIdle(5);
poolConfig.setMinIdle(2);
// 初始化连接池(默认localhost:6379)
jedisPool = new JedisPool(poolConfig, "localhost", 6379, 2000, "your-password");
// 如果没有密码:new JedisPool(poolConfig, "localhost", 6379);
}
public static void main(String[] args) {
try (Jedis jedis = jedisPool.getResource()) {
// ============ 哈希写入操作 ============
String userKey = "user:1001";
// 1. 单个字段写入
jedis.hset(userKey, "name", "张三");
jedis.hset(userKey, "age", "25");
jedis.hset(userKey, "city", "北京");
// 2. 批量写入
Map<String, String> userMap = new HashMap<>();
userMap.put("email", "zhangsan@example.com");
userMap.put("phone", "13800138000");
userMap.put("score", "95.5");
jedis.hmset(userKey, userMap);
// 3. 设置字段仅在不存在时生效
jedis.hsetnx(userKey, "name", "李四"); // 不会生效,因为name已存在
// ============ 哈希读取操作 ============
// 1. 获取单个字段
String name = jedis.hget(userKey, "name");
System.out.println("姓名: " + name);
// 2. 获取多个字段
String[] fields = {"name", "age", "city"};
java.util.List<String> values = jedis.hmget(userKey, fields);
System.out.println("多个字段值: " + values);
// 3. 获取所有字段和值
Map<String, String> allFields = jedis.hgetAll(userKey);
System.out.println("所有字段:");
allFields.forEach((field, value) ->
System.out.println(" " + field + ": " + value)
);
// 4. 获取所有字段名
java.util.Set<String> keys = jedis.hkeys(userKey);
System.out.println("所有字段名: " + keys);
// 5. 获取所有值
java.util.List<String> allValues = jedis.hvals(userKey);
System.out.println("所有值: " + allValues);
// ============ 其他操作 ============
// 判断字段是否存在
boolean exists = jedis.hexists(userKey, "name");
System.out.println("name字段是否存在: " + exists);
// 获取哈希长度
long length = jedis.hlen(userKey);
System.out.println("哈希长度: " + length);
// 获取所有字段值(按字段顺序返回)
java.util.List<String> allValuesOrdered = jedis.hvals(userKey);
System.out.println("所有字段值(无序): " + allValuesOrdered);
// 字段自增(用于数值类型)
jedis.hincrBy(userKey, "visitCount", 1);
jedis.hincrByFloat(userKey, "score", 2.5);
// 删除字段
jedis.hdel(userKey, "phone", "email");
} catch (Exception e) {
e.printStackTrace();
} finally {
// 关闭连接池
if (jedisPool != null) {
jedisPool.close();
}
}
}
}
使用Spring Data Redis操作Redis Hash
添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
配置文件 (application.yml)
spring:
redis:
host: localhost
port: 6379
password: your-password
timeout: 2000ms
lettuce:
pool:
max-active: 10
max-idle: 5
min-idle: 2
Service实现类
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.HashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@Service
public class HashRedisService {
@Autowired
private RedisTemplate<String, Object> redisTemplate;
// 获取HashOperations
private HashOperations<String, String, Object> getHashOps() {
return redisTemplate.opsForHash();
}
/**
* 写入单个字段
*/
public void put(String key, String field, Object value) {
getHashOps().put(key, field, value);
}
/**
* 批量写入
*/
public void putAll(String key, Map<String, Object> map) {
getHashOps().putAll(key, map);
}
/**
* 写入并设置过期时间
*/
public void putWithExpire(String key, String field, Object value, long timeout, TimeUnit unit) {
getHashOps().put(key, field, value);
redisTemplate.expire(key, timeout, unit);
}
/**
* 仅在字段不存在时写入
*/
public Boolean putIfAbsent(String key, String field, Object value) {
return getHashOps().putIfAbsent(key, field, value);
}
// ============ 读取操作 ============
/**
* 获取单个字段
*/
public Object get(String key, String field) {
return getHashOps().get(key, field);
}
/**
* 获取多个字段
*/
public List<Object> multiGet(String key, List<String> fields) {
return getHashOps().multiGet(key, fields);
}
/**
* 获取所有字段和值
*/
public Map<String, Object> getAll(String key) {
return getHashOps().entries(key);
}
/**
* 获取所有字段名
*/
public Set<String> getKeys(String key) {
return getHashOps().keys(key);
}
/**
* 获取所有值
*/
public List<Object> getValues(String key) {
return getHashOps().values(key);
}
// ============ 其他操作 ============
/**
* 判断字段是否存在
*/
public Boolean hasField(String key, String field) {
return getHashOps().hasKey(key, field);
}
/**
* 获取哈希长度
*/
public Long size(String key) {
return getHashOps().size(key);
}
/**
* 字段自增
*/
public Long increment(String key, String field, long delta) {
return getHashOps().increment(key, field, delta);
}
/**
* 浮点数字段自增
*/
public Double increment(String key, String field, double delta) {
return getHashOps().increment(key, field, delta);
}
/**
* 删除字段
*/
public Long delete(String key, String... fields) {
return getHashOps().delete(key, (Object[]) fields);
}
}
使用示例
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@SpringBootTest
public class HashRedisTest {
@Autowired
private HashRedisService hashRedisService;
@Test
public void testHashOperations() {
String userKey = "user:1001";
// 写入操作
Map<String, Object> userInfo = new HashMap<>();
userInfo.put("name", "张三");
userInfo.put("age", 25);
userInfo.put("city", "北京");
userInfo.put("email", "zhangsan@example.com");
hashRedisService.putAll(userKey, userInfo);
hashRedisService.putWithExpire(userKey, "temp", "临时数据", 10, TimeUnit.MINUTES);
// 读取操作
String name = (String) hashRedisService.get(userKey, "name");
System.out.println("姓名: " + name);
// 批量读取
List<Object> values = hashRedisService.multiGet(userKey, Arrays.asList("name", "age", "city"));
System.out.println("批量读取: " + values);
// 获取所有数据
Map<String, Object> allData = hashRedisService.getAll(userKey);
System.out.println("所有数据: " + allData);
// 自增操作
hashRedisService.increment(userKey, "visitCount", 1);
Long visitCount = (Long) hashRedisService.get(userKey, "visitCount");
System.out.println("访问次数: " + visitCount);
// 判断存在
boolean hasAge = hashRedisService.hasField(userKey, "age");
System.out.println("是否有age字段: " + hasAge);
// 删除字段
hashRedisService.delete(userKey, "email", "temp");
// 获取哈希大小
Long size = hashRedisService.size(userKey);
System.out.println("哈希大小: " + size);
}
}
实际应用场景示例
用户会话管理
@Service
public class UserSessionService {
@Autowired
private HashRedisService hashRedisService;
// 存储用户会话信息
public void saveUserSession(String sessionId, UserSession session) {
String key = "session:" + sessionId;
Map<String, Object> sessionMap = new HashMap<>();
sessionMap.put("userId", session.getUserId());
sessionMap.put("username", session.getUsername());
sessionMap.put("loginTime", session.getLoginTime());
sessionMap.put("ip", session.getIp());
hashRedisService.putWithExpire(key, "data", sessionMap, 30, TimeUnit.MINUTES);
hashRedisService.put(key, "active", true);
}
// 更新会话中的某个字段
public void updateLastAccessTime(String sessionId) {
String key = "session:" + sessionId;
hashRedisService.put(key, "lastAccessTime", System.currentTimeMillis());
redisTemplate.expire(key, 30, TimeUnit.MINUTES); // 续期
}
// 获取用户信息
public UserSession getSession(String sessionId) {
String key = "session:" + sessionId;
Map<String, Object> data = (Map<String, Object>) hashRedisService.get(key, "data");
if (data == null) return null;
UserSession session = new UserSession();
session.setUserId((Long) data.get("userId"));
session.setUsername((String) data.get("username"));
session.setLoginTime((Long) data.get("loginTime"));
session.setIp((String) data.get("ip"));
return session;
}
}
就是Java操作Redis哈希的完整案例,包含了Jedis和Spring Data Redis两种方式,以及实际应用场景,哈希类型非常适合存储对象数据,可以灵活地读写部分字段,比存储整个JSON字符串更加高效。