👀Redis 的 Hash 映射

在 Redis 中,哈希是一个字符串字段和字符串值之间的映射。它特别适合存储对象。Spring Data Redis 提供了多种方法来处理 Redis 哈希,下面我们会详细讨论。

✌1. 通过使用 HashOperations 和一个 serializer 直接映射

✍ 作用:

允许你使用 Redis 的哈希数据结构,直接存储、更新、删除和读取对象。

✍ 使用场景:

当你想要直接与 Redis 哈希交互,而不需要复杂的对象映射时。

✍ 优点:

  • 简单直接。
  • 可以使用自定义的 serializer。

✍ 缺点:

  • 需要手动处理序列化和反序列化。
  • 对于复杂的对象,可能需要更多的手动管理。

✍ 示例代码:

@Service
public class RedisHashService {

    @Autowired
    private StringRedisTemplate redisTemplate;

    public void saveUser(User user) {
        HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
        hashOps.put("user:" + user.getId(), "name", user.getName());
        hashOps.put("user:" + user.getId(), "age", String.valueOf(user.getAge()));
    }

    public User getUser(String userId) {
        HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
        Map<String, String> entries = hashOps.entries("user:" + userId);
        User user = new User();
        user.setId(userId);
        user.setName(entries.get("name"));
        user.setAge(Integer.parseInt(entries.get("age")));
        return user;
    }
}

✌2. 使用 Redis Repository

✍ 作用:

提供了一种类似于 JPA 的方式来管理 Redis 哈希数据。

✍ 使用场景:

当你希望使用更高级的、声明性的方式来管理 Redis 数据时。

✍ 优点:

  • 更高级的抽象。
  • 与 Spring Data JPA 类似的编程模型。

✍ 缺点:

  • 需要更多的配置。
  • 可能不是最高效的方法,特别是对于大量的数据操作。

✍ 示例代码:

// Entity
@RedisHash("user")
public class User {
    @Id
    private String id;
    private String name;
    private int age;
    // getters and setters
}

// Repository
public interface UserRepository extends CrudRepository<User, String> {
}

// Service
@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;

    public void saveUser(User user) {
        userRepository.save(user);
    }

    public User getUser(String userId) {
        return userRepository.findById(userId).orElse(null);
    }
}

✌3. 使用 HashMapperHashOperations

HashMapper 提供了一种将对象映射到 Redis 哈希和从 Redis 哈希映射回对象的方法。

✍ a. BeanUtilsHashMapper 使用 Spring 的 BeanUtils.

🎯 作用:

允许使用 Spring 的 BeanUtils 将 Java beans 映射到 Redis 哈希和反向映射。

🎯 使用场景:

当你的对象与 Redis 哈希有一对一的映射,并且你想要一个简单的方式来转换它们时。

🎯 优点:

  • 简单且易于使用。
  • 无需额外的配置或注解。

🎯 缺点:

  • 不适合复杂的对象结构。
  • 仅支持简单的数据类型。

🎯 示例代码:

@Service
public class UserServiceWithBeanUtils {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final HashMapper<User, String, String> mapper = new BeanUtilsHashMapper<>(User.class);

    public void saveUser(User user) {
        HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
        Map<String, String> mappedHash = mapper.toHash(user);
        hashOps.putAll("user:" + user.getId(), mappedHash);
    }

    public User getUser(String userId) {
        HashOperations<String, String, String> hashOps = redisTemplate.opsForHash();
        Map<String, String> loadedHash = hashOps.entries("user:" + userId);
        return mapper.fromHash(loadedHash);
    }
}

✍ b. ObjectHashMapper 使用 对象(Object)到哈希的映射.

  • 描述:这是Spring Data Redis的官方文档,其中详细描述了ObjectHashMapper的API。
  • 使用场景:当你需要在Spring Boot项目中使用Redis作为缓存或数据存储时,可以使用ObjectHashMapper来将Java对象映射到Redis的哈希数据结构。
  • 优点:提供了与Spring集成的简单方法,支持嵌套属性和简单类型,如String。
  • 缺点:需要对Spring Data Redis有一定的了解。
@Bean
public HashMapper<Object, byte[], byte[]> hashMapper() {
    return new ObjectHashMapper();
}

@Component
public class HashMapping<T> {
    @NonNull
    private StringRedisTemplate stringRedisTemplate;
    @NonNull
    private HashMapper<Object, byte[], byte[]> hashMapper;

    public void writeHash(String key, T t) {
        checkNotNull(key, "hash key cannot be null");
        checkNotNull(t, "hash value cannot be null");
        stringRedisTemplate.execute((RedisCallback<Void>) connection -> {
            Map<byte[], byte[]> mappedHash = hashMapper.toHash(t);
            connection.hMSet(key.getBytes(), mappedHash);
            return null;
        });
    }

    public T loadHash(String key) {
        checkNotNull(key, "hash key cannot be null");
        Map<byte[], byte[]> loadedHash = stringRedisTemplate.getConnectionFactory().getConnection().hGetAll(key.getBytes());
        return (T) hashMapper.fromHash(loadedHash);
    }
}

✍ c. Jackson2HashMapper

🎯 作用:

提供了使用 Jackson 库将对象映射到 Redis 哈希的方法。

🎯 使用场景:

当你想要使用 JSON 格式存储对象,并希望能够轻松地将对象映射到 Redis 哈希时。

🎯 优点:

  • 利用 Jackson 的强大功能。
  • 可以处理更复杂的对象结构。

🎯 缺点:

  • 需要 Jackson 依赖。
  • 可能不如其他简单映射器那么高效。

🎯 示例代码:

@Service
public class UserServiceWithJackson {

    @Autowired
    private StringRedisTemplate redisTemplate;

    private final HashMapper<Object, byte[], byte[]> mapper = new Jackson2HashMapper(false);

    public void saveUser(User user) {
        HashOperations<String, byte[], byte[]> hashOps = redisTemplate.opsForHash();
        Map<byte[], byte[]> mappedHash = mapper.toHash(user);
        hashOps.putAll("user:" + user.getId(), mappedHash);
    }

    public User getUser(String userId) {
        HashOperations<String, byte[], byte[]> hashOps = redisTemplate.opsForHash();
        Map<byte[], byte[]> loadedHash = hashOps.entries("user:" + userId);
        return (User) mapper.fromHash(loadedHash);
    }
}

总结:Spring Data Redis 提供了多种方法来处理和管理 Redis 的哈希数据结构,从简单的直接操作到更复杂的对象映射方法。选择哪种方法取决于你的具体需求和偏好。