You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义Spring Data JPA @Query查询Postgres JsonB时参数失效无结果

问题分析与解决方案

核心错误点

你最初的@Query写法里,:num和:status被包裹在JSON字符串字面量'{"num" :num, "status" :status}'内部,JPA不会解析字符串里的参数占位符,导致实际执行的查询是匹配data包含{"num" :num, "status" :status}这个字面JSON,而非你传入的参数值,所以返回0条结果。

正确的实现方式

1. 修复多参数的@>查询(推荐方式)

用PostgreSQL内置的jsonb_build_object函数动态构建JSONB对象,让JPA正确绑定参数:

@Repository
interface MyRepository : CrudRepository<MyEntity, Long> {
    @Query("SELECT * FROM mydb.public.mytable WHERE data @> jsonb_build_object('num', :num, 'status', :status)")
    fun findByNumAndStatus(num: String, status: String): List<MyEntity>
}

这个方法不需要手动拼接字符串,既安全又避免转义错误,PostgreSQL会自动把参数转换成JSONB类型进行匹配。

2. 单参数查询的修复

你尝试的单参数查询在数据库客户端正常,但在@Query中失效,大概率是以下两个原因:

  • 参数名未正确绑定:Kotlin默认编译时不会保留参数名,Spring Data无法自动识别num参数,需要用@Param注解显式指定:
    @Query("SELECT * FROM mydb.public.mytable t WHERE t.data ->> 'num' = :num")
    fun findByNum(@Param("num") num: String): List<MyEntity>
    
    或者在项目构建配置中开启Kotlin的参数名保留(比如在build.gradle中添加kotlinOptions { freeCompilerArgs += "-Xemit-jvm-type-annotations"; jvmTarget = "17" }),这样就不用写@Param。
  • 参数类型不匹配:如果用data @> :num这种写法,需要确保参数是JSONB类型。如果传入的是字符串,要手动转换类型:
    @Query("SELECT * FROM mydb.public.mytable WHERE data @> :num::jsonb")
    fun findByNumJson(@Param("num") num: String): List<MyEntity>
    
    或者直接传入JSON对象(比如Jackson的JsonNode),Spring Data会自动适配PostgreSQL的JSONB类型:
    import com.fasterxml.jackson.databind.JsonNode
    
    @Repository
    interface MyRepository : CrudRepository<MyEntity, Long> {
        @Query("SELECT * FROM mydb.public.mytable WHERE data @> :num")
        fun findByNumJson(@Param("num") num: JsonNode): List<MyEntity>
    }
    

额外检查点

确认你的MyEntity类中data字段的映射是否正确,需要指定JSONB类型:

import javax.persistence.Column
import javax.persistence.Entity
import javax.persistence.Id

@Entity(name = "mytable")
class MyEntity(
    @Id val id: Long,
    @Column(columnDefinition = "jsonb") val data: String // 或者用JsonNode类型,需配合Hibernate的JSONB类型转换器
)

如果用Hibernate 5.2+,可以直接用@Type(type = "jsonb")来映射JsonNode类型,避免字符串手动转换。

内容的提问来源于stack exchange,提问作者Johnny Alpha

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.26 05:45:32