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

迁移至Spring Boot 2.0.0.RELEASE后遇"Got different size of tuples and aliases"异常求助

解决Spring Boot 2.0.0.RELEASE中NamedNativeQuery返回非实体POJO的"Got different size of tuples and aliases"异常

这个问题大概率是因为Spring Boot 2.0.0.RELEASE对应的Hibernate版本(5.2.x系列)对结果集到非实体POJO的映射做了更严格的校验,而你之前依赖的隐式映射逻辑在正式版中被收紧了。下面是具体的排查和解决步骤:

1. 核对结果集列数与POJO属性/构造参数数量

首先要确认存储过程返回的列的数量,和你用来接收结果的POJO的属性数量(如果用setter注入)或者构造函数参数数量(如果用构造函数注入)完全一致。新版本的Hibernate会严格校验这个匹配度,哪怕多一列或少一列都会抛出这个异常。

2. 显式定义结果集映射(推荐方案)

在Spring Boot 2.0之前的版本,可能允许Hibernate隐式地将结果集映射到POJO,但正式版中更推荐显式使用@SqlResultSetMapping和@ConstructorResult来绑定结果:

步骤1:给POJO定义结果集映射

在你的实体类或者POJO类上添加@SqlResultSetMapping(注意:如果POJO不是实体类,这个注解需要放在任意一个实体类上,因为JPA要求映射定义在实体类或包级注解中):

@Entity
@SqlResultSetMapping(
    name = "UserStatsMapping",
    classes = @ConstructorResult(
        targetClass = UserStatsPojo.class,
        columns = {
            @ColumnResult(name = "user_id", type = Long.class),
            @ColumnResult(name = "total_orders", type = Integer.class),
            @ColumnResult(name = "last_login", type = LocalDateTime.class)
        }
    )
)
public class User {
    // 实体类内容
}

这里的columns数组要和存储过程返回的列名完全对应,targetClass是你的非实体POJO,同时要确保POJO有对应参数顺序和类型的构造函数:

public class UserStatsPojo {
    private Long userId;
    private Integer totalOrders;
    private LocalDateTime lastLogin;

    // 构造函数参数顺序要和@ColumnResult的顺序完全一致
    public UserStatsPojo(Long userId, Integer totalOrders, LocalDateTime lastLogin) {
        this.userId = userId;
        this.totalOrders = totalOrders;
        this.lastLogin = lastLogin;
    }

    // getter方法
}

步骤2:在NamedNativeQuery中引用这个映射

修改你的@NamedNativeQuery,指定resultSetMapping为上面定义的映射名称:

@NamedNativeQuery(
    name = "User.getUserStats",
    query = "CALL get_user_stats(:userId)",
    resultSetMapping = "UserStatsMapping"
)

3. 确保列别名与POJO属性名完全匹配(如果用setter注入)

如果你之前是依赖无参构造函数+setter方法来注入结果,那要确保存储过程返回的列别名和POJO的属性名完全一致(包括大小写,部分数据库对大小写敏感)。比如POJO属性是userId,存储过程返回的列别名必须是user_id(对应下划线转驼峰的命名策略)或者直接是userId,具体取决于你的Hibernate命名配置。

如果存储过程返回的列名和POJO属性名不匹配,可以在查询中手动指定别名(不同数据库语法可能有差异,需按需调整):

CALL get_user_stats(:userId) AS user_id, total_orders, last_login

4. 检查Hibernate命名策略配置

Spring Boot 2.0中默认的Hibernate命名策略从SpringNamingStrategy改成了SpringPhysicalNamingStrategy,这个策略会将数据库列名的下划线自动转成驼峰式的属性名。如果你之前依赖旧的命名策略,可能需要在application.properties中显式配置:

spring.jpa.hibernate.naming.physical-strategy=org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
spring.jpa.hibernate.naming.implicit-strategy=org.hibernate.boot.model.naming.ImplicitNamingStrategyLegacyJpaImpl

不过更推荐的还是用显式的结果集映射,避免依赖命名策略的隐式转换。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:58:50