Criteria API构造查询无返回但手动执行可命中结果问题排查
问题原因
是的,你在Criteria API中添加的to_jsonb函数调用就是查询无结果的直接原因。
两者的核心差异在于PostgreSQL对两种写法的处理逻辑完全不同:
- 你手动执行的SQL中,直接传入带单引号的JSON格式字符串,PostgreSQL会自动将其隐式转换为JSONB类型的数组结构
[{"key":"supplierProductId", "value":"123-123-12348"}],和metadata_items的JSONB数组结构匹配,因此可以正常命中jsonb_contains的匹配规则。 - 而你的Criteria API生成的SQL中,使用
to_jsonb(?)处理传入的字符串参数:to_jsonb函数如果接收字符串类型的输入,会直接把整个字符串转换为JSONB字符串标量,也就是最终传入jsonb_contains的第二个参数是"[{\"key\":\"supplierProductId\", \"value\":\"123-123-12348\"}]"(外层带引号的JSON字符串,不是数组结构),和metadata_items的数组结构完全不匹配,自然返回空结果。
解决方案
你不需要强行添加to_jsonb函数调用,可选两种修正方式:
- 方式1:显式指定参数的JSONB类型映射,让EclipseLink直接把字符串参数作为JSONB类型传入,不需要额外函数转换。你可以在构造
literal时指定对应的JDBC类型为JSONB专属类型,或者给实体类的metadataItems字段配置正确的JSONB类型转换器。 - 方式2:如果必须通过函数做类型转换,把
to_jsonb替换为cast操作,比如将代码修改为:
Expression<Boolean> fun = cb.function("jsonb_contains", Boolean.class, r.get(MediaEntity_.metadataItems), cb.function("cast", Object.class, cb.literal("[{\"key\":\"supplierProductId\", \"value\":\"123-123-12348\"}]"), cb.literal("jsonb") ) );
cast(? as jsonb)会把输入的字符串内容解析为对应的JSON结构,和你手动写SQL的效果一致。
内容的提问来源于stack exchange,提问作者Uros K
相关产品推荐
相关产品推荐

