在Spring Boot(Kotlin+Redis OM Spring)中使用投影查询Redis JSON指定字段返回null的问题排查
在Spring Boot(Kotlin+Redis OM Spring)中使用投影查询Redis JSON指定字段返回null的问题排查
我帮你捋捋这个问题哈,你现在遇到的情况是Redis CLI里明明能查到正确的number和location数据,但Spring这边用投影接口返回的全是null,这其实是Redis OM Spring结合Kotlin使用投影时的一个常见小问题,咱们一步步来解决:
1. 先搞懂问题出在哪
你在Redis CLI里看到的查询结果是完全正常的,说明Redis那边的FT.SEARCH命令执行没问题,问题出在Spring端把Redis返回的结果映射到Stat接口实例的过程中,主要有两个核心原因:
- Kotlin接口投影默认生成的代理类,没法正确触发Redis OM Spring对
Point这类Geo复杂类型的反序列化逻辑; - Redis OM Spring在Kotlin下对接口属性的访问器(也就是Getter方法)的识别逻辑和Java略有差异,导致没法把Redis返回的字段值正确绑定到接口属性上。
2. 最靠谱的解决方案:用数据类代替接口做投影
Spring Data的DTO投影(也就是用数据类做投影)会通过构造函数直接绑定字段值,比接口投影更稳定,尤其是处理Point这种复杂类型的时候,咱们这么改:
第一步:把投影接口改成Kotlin数据类
import org.springframework.data.geo.Point // 用数据类替代原来的Stat接口 data class Stat( val number: String, val location: Point )
第二步:修改Repository的返回类型
interface MarkerRepo : RedisDocumentRepository<RedisMarker, String> { // 返回List<Stat>,对应新的投影数据类 fun findByNumber(number: String): List<Stat> }
改完之后,Redis OM Spring就能正确把Redis返回的number字符串和location坐标字符串,反序列化成Stat数据类的实例,不会再返回null列表啦。
3. 要是坚持用接口投影,试试这个调整
如果你一定要用接口作为投影,可以给接口的属性加上@JsonProperty注解,明确指定和Redis返回字段的映射关系,帮Spring正确识别字段:
import com.fasterxml.jackson.annotation.JsonProperty import org.springframework.data.geo.Point interface Stat { @JsonProperty("number") val number: String @JsonProperty("location") val location: Point }
不过这个方案的稳定性不如数据类投影,因为Kotlin接口生成的代理类逻辑和Java有细微差异,复杂类型的反序列化还是可能出问题,所以更推荐用数据类的方案。
4. 最后再提两个注意点
- 确保你的Redis OM Spring是最新稳定版本,旧版本可能存在Kotlin投影的兼容性bug;
- 检查
Point类型的导入:必须是org.springframework.data.geo.Point,这是Redis OM Spring默认支持的Geo类型,别用自定义的Point类,不然反序列化肯定失败。
内容来源于stack exchange
相关产品推荐
相关产品推荐

