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

Spring Boot原生MySQL查询自动添加()引发语法异常求助

Spring Boot 3.x 原生JPA查询List参数被自动加括号导致MySQL语法错误

问题场景

在Spring Boot 2.4.4中正常运行的原生MySQL查询,升级到Spring Boot 3.0.6后,IN子句和FIELD函数中的List参数被自动包裹额外括号,引发MySQL语法异常。

原Repository查询代码:

@Query(value = "SELECT id FROM example WHERE id IN ?1 ORDER BY FIELD(id , ?1) " ,nativeQuery = true)
List<String> testQuery(List<String> ids);

Spring Boot 3.x中生成的错误SQL示例:

SELECT id FROM example WHERE id IN (('id1','id2')) ORDER BY FIELD(id , ('id1','id2'))

多余的嵌套括号导致MySQL报错。


解决方案

方案1:使用SpEL表达式展开List参数

通过Spring Data JPA的SpEL表达式,手动将List展开为符合MySQL语法的参数格式:

@Query(value = "SELECT id FROM example WHERE id IN (?#{T(org.springframework.data.jpa.repository.query.QueryUtils).toInClauseString(#ids)}) " +
               "ORDER BY FIELD(id, ?#{#ids.stream().collect(T(java.util.stream.Collectors).joining('\',\''))})", nativeQuery = true)
List<String> testQuery(@Param("ids") List<String> ids);
  • QueryUtils.toInClauseString 用于生成正确的IN子句参数
  • 流操作将List转为逗号分隔的字符串,适配FIELD函数的参数要求

方案2:直接使用NamedParameterJdbcTemplate手动执行查询

完全绕过JPA的参数处理逻辑,手动拼接SQL并执行,精准控制参数格式:

@Repository
public class ExampleCustomRepository {

    private final NamedParameterJdbcTemplate jdbcTemplate;

    public ExampleCustomRepository(NamedParameterJdbcTemplate jdbcTemplate) {
        this.jdbcTemplate = jdbcTemplate;
    }

    public List<String> testQuery(List<String> ids) {
        // 生成对应数量的占位符
        String placeholders = String.join(",", Collections.nCopies(ids.size(), "?"));
        String sql = String.format("SELECT id FROM example WHERE id IN (%s) ORDER BY FIELD(id, %s)", placeholders, placeholders);
        
        // 合并参数:IN子句和FIELD函数各需要一次ids列表
        List<Object> params = new ArrayList<>(ids);
        params.addAll(ids);
        
        return jdbcTemplate.query(sql, params.toArray(), (rs, rowNum) -> rs.getString("id"));
    }
}

在Controller中注入ExampleCustomRepository替代原JPA Repository即可。

方案3:拆分List参数为固定数量的独立参数(仅适用于参数长度固定场景)

如果传入的List长度固定,可以直接拆分为多个参数:

@Query(value = "SELECT id FROM example WHERE id IN (?1, ?2, ?3) ORDER BY FIELD(id, ?1, ?2, ?3)", nativeQuery = true)
List<String> testQuery(String id1, String id2, String id3);

注意:此方法仅适合参数数量固定的场景,灵活性较差。

方案4:临时降级Hibernate版本(不推荐长期使用)

在Spring Boot 3.x的pom.xml中指定兼容的Hibernate版本,临时规避参数处理逻辑的变化:

<properties>
    <hibernate.version>6.1.7.Final</hibernate.version>
</properties>

该方案可能引入其他兼容性问题,仅作为临时应急方案。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 19:40:06