Spring JPA原生查询PostgreSQL JSONB字段参数混合报错排查
Spring JPA原生查询PostgreSQL jsonb字段报错解决
问题场景
要通过Spring JPA原生查询筛选PostgreSQL数据库中,jsonb类型字段severity_map包含指定键的数据。原始SQL语句如下:
select * FROM targeted_event_catalog e WHERE e.severity_map ? 'serviceName';
对应的Spring JPA代码实现:
@Query(value = "SELECT * FROM targeted_event_catalog e WHERE e.severity_map ? :service", nativeQuery = true) List<TargetedEventRegistration> findByService(@Param("service") String service);
执行时抛出错误:
Caused by: java.lang.IllegalArgumentException: Mixing of ? parameters and other forms like ?1 is not supported
severity_map字段的数据示例:
{"serviceName": ["info", "warning", "critical"]}
尝试使用??替代?后仍未解决问题。
错误原因
PostgreSQL中?是jsonb类型的键存在性检查运算符,但在Spring JPA的原生查询解析逻辑中,?会被识别为参数占位符。此时SQL中同时存在运算符?和命名参数:service,导致参数解析逻辑混乱,触发了参数混合使用的异常。
解决方法
方案1:使用PostgreSQL内置函数替代运算符
直接使用PostgreSQL提供的jsonb_exists函数检查jsonb字段是否包含指定键,避免和Spring的参数占位符冲突:
@Query(value = "SELECT * FROM targeted_event_catalog e WHERE jsonb_exists(e.severity_map, :service)", nativeQuery = true) List<TargetedEventRegistration> findByService(@Param("service") String service);
方案2:转义运算符并使用位置参数
如果要保留?运算符,需要用??进行转义,同时改用位置参数(不能混合命名参数):
@Query(value = "SELECT * FROM targeted_event_catalog e WHERE e.severity_map ?? ?1", nativeQuery = true) List<TargetedEventRegistration> findByService(String service);
这里第一个?用于转义PostgreSQL的运算符,第二个?1是Spring的位置参数占位符,对应方法的第一个入参。
内容的提问来源于stack exchange,提问作者Koushik J
相关产品推荐
相关产品推荐

