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

Spring Boot 2迁3时@EmbeddedId复合主键JPA查询异常问题

问题原因及解决方案

这个问题本质是Spring Boot 3(搭配Hibernate 6)对复合主键IN查询的SQL生成逻辑发生了变更,具体原因如下:

  1. 依赖版本升级带来的规范适配
    Spring Boot 3对应Spring Data JPA 3.x和Hibernate 6.x,这两个版本全面适配JPA 3.0规范,其中包含了对**行值表达式(Row Value Expressions)**的支持。Hibernate 6默认会将复合主键的findAllById查询转换为行值表达式语法,比如生成:

    WHERE (e.param1, e.param2) IN ((?, ?), (?, ?))
    

    你看到的错误语法(e.param1,e.param2 IN (?,?))是行值表达式的简化输出形式,本质是Hibernate尝试用新语法匹配复合主键集合。

  2. 老版本数据库兼容性问题
    之前在Spring Boot 2+Hibernate 5环境下正常,是因为Hibernate 5不支持行值表达式,会自动将复合主键拆解为多个AND条件的SQL。但部分老版本数据库(比如MySQL 5.x、某些低版本PostgreSQL)不支持JPA 3.0的行值表达式语法,导致SQL执行报错。


解决办法

可以根据你的数据库环境选择以下方案:

  • 方案一:升级数据库版本
    若条件允许,将数据库升级到支持行值表达式的版本(比如MySQL 8.0+、PostgreSQL 9.4+),直接适配Hibernate 6的新语法。

  • 方案二:回退Hibernate的SQL生成逻辑
    在application.properties或application.yml中添加配置,强制Hibernate使用旧的复合主键拆解方式:

    spring.jpa.properties.hibernate.query.legacy_row_value_expression_handler=true
    

    配置后Hibernate会回到Hibernate 5的行为,生成e.param1 = ? AND e.param2 = ?的条件组合。

  • 方案三:自定义Repository查询方法
    手动编写JPQL查询,明确指定复合主键的匹配逻辑,例如:

    public interface EntityRepository extends JpaRepository<Entity, Pk> {
        @Query("SELECT e FROM Entity e WHERE (e.id.param1, e.id.param2) IN :ids")
        List<Entity> findAllByCompositeIds(@Param("ids") Iterable<Pk> ids);
    }
    

    若数据库不支持行值表达式,也可以拆解为多个OR条件(适合主键数量不多的场景):

    @Query("SELECT e FROM Entity e WHERE " +
           "(:ids IS NULL OR " +
           " (e.id.param1 = (SELECT p.param1 FROM :ids p WHERE p.param2 = e.id.param2) AND e.id.param2 IN (SELECT p.param2 FROM :ids p)))")
    List<Entity> findAllByCompositeIds(@Param("ids") Iterable<Pk> ids);
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 20:22:39