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

迁移到Hibernate 6与Spring Boot 3后createNativeQuery无法正常工作的问题求助

迁移到Hibernate 6与Spring Boot 3后createNativeQuery无法正常工作的问题求助

这个问题我之前帮朋友排查过类似的,Hibernate 6相对于Hibernate 5在原生查询的参数类型推断上做了更严格的限制,尤其是枚举集合这类特殊类型,PostgreSQL没办法自动识别参数的类型,所以抛出了这个“无法确定参数$3的数据类型”的错误。下面给你几个可行的解决思路:

方法1:在SQL中显式转换参数为枚举类型

你的原SQL里还有个小疏漏:coalesce(statuses)应该写成coalesce(:statuses)(少了冒号),不然PostgreSQL会把statuses当成列名处理。修改后的SQL通过unnest展开集合参数,再显式转换为你的枚举类型as_status_type,让PostgreSQL明确知道参数类型:

select
    *
from earp.as sys
where
    (sys.id = :id or sys.parent_id = :id)
  and (coalesce(:statuses) is null
    or (sys.status not in (select cast(unnest(:statuses) as as_status_type)))
    )

方法2:在设置参数时显式指定枚举类型

Hibernate 6允许我们在设置参数时直接指定类型,告诉Hibernate这是一个枚举集合,这样PostgreSQL就能正确识别类型了。你可以用EnumType来指定:

return entityManager.unwrap(Session.class)
        .createNativeQuery(sql, Tuple.class)
        .setParameter("id", id)
        // 如果你是用字符串枚举映射
        .setParameter("statuses", statuses, EnumType.STRING.asParameterType())
        // 如果你是直接映射数据库枚举类型,用下面的方式(需要引入Hibernate的EnumType)
        // .setParameter("statuses", statuses, new EnumType<>(AsStatusType.class, EnumType.NamingStrategy.EXPLICIT))
        .getResultStream();

方法3:提前处理空集合的分支逻辑

Hibernate 6对空集合参数的处理逻辑和Hibernate 5不同,你可以在Java代码里提前判断statuses是否为空,动态拼接SQL,避免空集合导致的类型推断问题:

// 基础SQL
StringBuilder sqlBuilder = new StringBuilder("select * from earp.as sys where (sys.id = :id or sys.parent_id = :id)");

// 先初始化基础查询
var baseQuery = entityManager.unwrap(Session.class)
        .createNativeQuery(sqlBuilder.toString(), Tuple.class)
        .setParameter("id", id);

// 只有当statuses非空时,才添加条件并设置参数
if (statuses != null && !statuses.isEmpty()) {
    sqlBuilder.append(" and sys.status not in (:statuses)");
    // 重新生成包含新条件的查询
    return entityManager.unwrap(Session.class)
            .createNativeQuery(sqlBuilder.toString(), Tuple.class)
            .setParameter("id", id)
            .setParameter("statuses", statuses, EnumType.STRING.asParameterType())
            .getResultStream();
}

return baseQuery.getResultStream();

另外,还要检查一下你的枚举类型映射是否正确,Hibernate 6中枚举的JPA注解可能需要调整,比如用@JdbcTypeCode(SqlTypes.ENUM)来明确指定是数据库枚举类型,不过这里是原生查询,主要还是参数类型的问题。

备注:内容来源于stack exchange,提问作者Mike Sonarov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 19:20:28