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

Spring Boot3迁移后@Formula字段原生查询报错问题求助

问题原因分析

Spring Boot 3 对应的 Hibernate 版本(通常为 6.x 系列)对原生查询的实体映射逻辑做了严格调整:

  • findAll() 这类方法是 Spring Data 生成的 HQL 查询,Hibernate 会自动将 @Formula 注解的计算逻辑注入到生成的 SQL 中,因此能正确返回 fullName 字段。
  • 自定义原生查询 SELECT distinct p.* FROM persons p 仅返回数据库表中存在的列,不包含 @Formula 定义的计算列,而 Hibernate 6 不再像旧版本(Spring Boot 2 对应的 Hibernate 5.x)那样自动为 @Formula 字段补全计算,而是直接从 ResultSet 中查找该列,最终因找不到字段报错。
解决方案

提供三种可行方案,按需选择:

方案1:修改原生查询,手动添加计算列

直接在原生查询中加入 @Formula 的计算逻辑,并指定别名 fullName,让 ResultSet 包含该字段:

@Query(value = "SELECT distinct p.*, CONCAT_WS( ' ', p.surname, p.name, p.middle_name ) AS fullName FROM persons p", nativeQuery = true)
List<Person> findBySomeCustomRequest();

这样 Hibernate 就能从查询结果中找到 fullName 列,完成实体映射。

方案2:将计算逻辑移至内存(替换@Formula)

去掉 @Formula 和 @NotAudited 注解,通过实体的 getter 方法在内存中计算全名,避免依赖数据库返回计算列:

// 移除原有@Formula和@NotAudited注解
private String fullName; // 若无需持久化可添加@Transient注解,或直接去掉字段仅保留getter

public String getFullName() {
    // 处理null值,避免拼接出多余空格
    StringBuilder sb = new StringBuilder(surname);
    if (name != null && !name.isBlank()) {
        sb.append(" ").append(name);
    }
    if (middleName != null && !middleName.isBlank()) {
        sb.append(" ").append(middleName);
    }
    return sb.toString();
}

这种方式不受查询类型限制,原生查询或 HQL 都能正常获取 fullName。

方案3:改用HQL查询替代原生查询

如果业务允许,将原生查询改为 HQL,Hibernate 会自动处理 @Formula 的计算逻辑:

@Query(value = "SELECT distinct p FROM Person p")
List<Person> findBySomeCustomRequest();

HQL 查询会自动生成包含 fullName 计算逻辑的 SQL,无需手动处理字段映射。

内容的提问来源于stack exchange,提问作者Артем Косенко

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 14:03:22