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。支持String
、Integer
等基本类型。
💡 踩坑提示:@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