1. 简介

Spring Data Key Value 是 Spring Data 家族中用于支持键值存储(Key-Value Store)的模块。它能显著减少与 KV 存储交互时的模板代码和重复劳动,让开发更高效。

该框架对 Redis、Riak 等主流键值数据库有良好支持。但在本篇中,我们聚焦于其内置的基于 java.util.Map 的默认实现,帮助你快速理解核心机制,避免被外部依赖干扰。

✅ 适合用于本地缓存、测试环境或轻量级数据管理场景。
❌ 不适用于生产级高并发、持久化强需求的场景(那是 Redis 的主场)。


2. 环境要求

  • JDK 版本:6.0 或以上
  • Spring Framework:3.0.x 或以上

⚠️ 当前实际项目中建议使用 JDK 8+ 和 Spring Boot 2.x+,本文示例基于现代开发环境调整。


3. Maven 依赖

引入 spring-data-keyvalue 即可:

<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-keyvalue</artifactId>
    <version>2.0.6.RELEASE</version>
</dependency>

📌 最新版本可查阅 Maven Central


4. 定义实体类

我们以 Employee 为例,定义一个简单的实体:

@KeySpace("employees")
public class Employee {

    @Id
    private Integer id;

    private String name;
    private String department;
    private String salary;

    // 构造函数、getter/setter 略
}

关键点说明:

  • @KeySpace("employees"):指定该实体存储的“命名空间”,类似于 MongoDB 的集合、JPA 的表。不加的话默认使用类名。
  • @Id:标识主键字段,用于生成 key。支持 StringInteger 等基本类型。

💡 踩坑提示:@Id 字段必须可序列化,否则运行时报错。


5. 配置仓库(Repository)

和 Spring Data JPA 一样,我们通过接口定义仓库,框架自动生成实现。

启用 Map 仓库

使用 @EnableMapRepositories 注解开启支持:

@SpringBootApplication
@EnableMapRepositories
public class SpringDataKeyValueApplication {
}

默认底层使用 ConcurrentHashMap,线程安全,适合大多数场景。

自定义 Map 实现

如果想换其他 Map 实现(比如弱引用缓存),可以指定:

@EnableMapRepositories(mapType = WeakHashMap.class)

定义 EmployeeRepository

@Repository
public interface EmployeeRepository 
    extends CrudRepository<Employee, Integer> {
}
  • ✅ 继承 CrudRepository 后,自动获得 CRUD 方法。
  • ✅ 泛型参数:<Employee, Integer> 分别表示实体类型和主键类型。

📌 更多关于 Spring Data Repository 的机制,可参考官方文档或相关深度文章。


6. 使用 Repository 操作数据

6.1 保存对象

Employee employee = new Employee(1, "Mike", "IT", "5000");
employeeRepository.save(employee);

✅ 会以 @Id 值作为 key,序列化对象存入 Map。


6.2 查询单个对象

Optional<Employee> savedEmployee = employeeRepository.findById(1);

✅ 返回 Optional,避免空指针,标准写法。


6.3 更新对象

CrudRepository 没有独立的 update 方法,统一用 save() 实现更新

employee.setName("Jack");
employeeRepository.save(employee);

⚠️ 注意:只要 @Id 存在且已存在,就是更新操作。Spring Data Key Value 内部会覆盖原值。


6.4 删除对象

employeeRepository.deleteById(1);

简单粗暴,按 ID 删就完事了。


6.5 查询所有对象

Iterable<Employee> employees = employeeRepository.findAll();

返回所有 employees keyspace 下的对象。


7. KeyValueTemplate 简介

除了 Repository 模式,Spring Data Key Value 还提供了 KeyValueTemplate,更适合复杂操作或动态查询。

它通过 MapAdapter 包装任意 Map 实现来完成数据操作。

手动配置 Template(非必须)

@Bean
public KeyValueOperations keyValueTemplate() {
    return new KeyValueTemplate(keyValueAdapter());
}

@Bean
public KeyValueAdapter keyValueAdapter() {
    return new MapKeyValueAdapter(WeakHashMap.class);
}

📌 注意:如果你已经用了 @EnableMapRepositories,**无需手动配置 KeyValueTemplate**,框架会自动注册一个可用的 Bean。


8. 使用 KeyValueTemplate

8.1 保存对象

Employee employee = new Employee(1, "Mile", "IT", "5000");
keyValueTemplate.insert(employee);

insert() 强调“插入”,如果 key 已存在可能抛异常(取决于实现)。


8.2 查询单个对象

Optional<Employee> savedEmployee = keyValueTemplate
  .findById(1, Employee.class);

需要显式传入类型,因为泛型擦除。


8.3 更新对象

employee.setName("Jacek");
keyValueTemplate.update(employee);

✅ 与 Repository 不同,KeyValueTemplate 提供了专用的 update() 方法,语义更清晰。


8.4 删除对象

keyValueTemplate.delete(1, Employee.class);

指定 ID 和类型即可。


8.5 查询所有对象

Iterable<Employee> employees = keyValueTemplate
  .findAll(Employee.class);

同 Repository,但底层走的是 Template 通道。


8.6 支持排序查询

这是 KeyValueTemplate 的优势所在 —— 支持 KeyValueQuery,可以做简单排序。

例如:按薪资降序查询所有员工

KeyValueQuery<Employee> query = new KeyValueQuery<>();
query.setSort(new Sort(Sort.Direction.DESC, "salary"));
Iterable<Employee> employees = keyValueTemplate.find(query, Employee.class);

✅ 虽然功能不如 JPA 的 Pageable 强大,但在 Map 场景下够用。
⚠️ 排序基于反射读取字段值,注意性能影响。


9. 总结

本文带你实战了 Spring Data Key Value 的核心用法:

  • 使用 @EnableMapRepositories 快速启用基于 Map 的 KV 存储
  • 通过 @KeySpace@Id 定义实体结构
  • 利用 CrudRepository 实现标准 CRUD
  • 使用 KeyValueTemplate 进行更灵活的操作,如排序查询

📌 该模块更多是作为底层抽象存在,实际生产中更多用于构建上层框架,比如:

✅ Spring Data Redis 就是基于 Spring Data Key Value 构建的!

想了解更实用的场景?推荐阅读 《Spring Data Redis 入门教程》

所有示例代码已托管至 GitHub:
👉 https://github.com/eugenp/tutorials/tree/master/persistence-modules/spring-data-keyvalue


原始标题:A Guide to Spring Data Key Value