Hibernate中使用Postgres JSON函数时的参数注入问题
解决Hibernate原生查询中Postgres jsonb_path_exists参数绑定失效的问题
下面是几个可行的替代方案:
方案1:使用jsonb_path_exists的变量参数传递
PostgreSQL的jsonb_path_exists函数支持第三个参数传递变量对象,通过这种方式可以避免直接在JSON路径字符串中注入参数,让Hibernate正确绑定参数:
@Query(value = "SELECT * FROM foo WHERE jsonb_path_exists(CAST(foo.things AS jsonb), '$[*] ? (@.id == $banana_id)', jsonb_build_object('banana_id', :banana_id))", nativeQuery = true) List<Foo> findByThingBananaId(@Param("banana_id") String bananaId);
- 原理:用
jsonb_build_object将参数打包为JSON变量,在JSON路径中通过$banana_id引用该变量,Hibernate可以正常识别并绑定:banana_id参数。
方案2:改用jsonb_array_elements配合EXISTS子查询
将JSON数组拆分为行记录后,直接用普通的参数匹配逻辑筛选,兼容性更强:
@Query(value = "SELECT f.* FROM foo f WHERE EXISTS (SELECT 1 FROM jsonb_array_elements(CAST(f.things AS jsonb)) elem WHERE elem->>'id' = :banana_id)", nativeQuery = true) List<Foo> findByThingBananaId(@Param("banana_id") String bananaId);
- 如果
foo.things字段本身就是jsonb类型,可以去掉CAST(foo.things AS jsonb)转换操作。
方案3:使用jsonb的@>操作符(适用于精确匹配元素场景)
如果只需要匹配数组中包含完整{"id": "xxx"}结构的元素,可以将参数包装为JSON数组字符串后用@>操作符:
@Query(value = "SELECT * FROM foo WHERE CAST(foo.things AS jsonb) @> :matchObj", nativeQuery = true) List<Foo> findByThingBananaId(@Param("matchObj") String matchObj);
调用时传入格式为"[{\"id\": \"你的banana_id值\"}]"的字符串即可,注意如果id是数值类型,要去掉引号。
内容的提问来源于stack exchange,提问作者evilfred
相关产品推荐
相关产品推荐

