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

Hibernate5.3.4 Oracle12cDialect变更导致分页排序报ORA-01791错误如何解决

问题原因

这个是Hibernate 5.3.4版本的已知变更:因之前Oracle12cDialect使用SQL2008StandardLimitHandler存在其他兼容性问题,官方在5.3.4版本将其默认LimitHandler回退为Oracle9i版本的嵌套分页实现,才导致了你遇到的ORA-01791错误——Oracle要求嵌套分页场景下,子查询中ORDER BY用到的字段必须出现在子查询的SELECT列表中,而你的原查询仅查询了User实体字段,关联表的排序字段不在SELECT列表内,因此执行报错。

修复方案

方案1:自定义方言(最稳妥,无业务代码侵入)

继承官方Oracle12cDialect,重写LimitHandler返回逻辑,强制使用SQL2008标准的分页语法:

import org.hibernate.dialect.Oracle12cDialect;
import org.hibernate.dialect.pagination.LimitHandler;
import org.hibernate.dialect.pagination.SQL2008StandardLimitHandler;

public class CustomOracle12cDialect extends Oracle12cDialect {
    @Override
    public LimitHandler getLimitHandler() {
        return SQL2008StandardLimitHandler.INSTANCE;
    }
}

修改Hibernate配置文件中的方言配置,替换为你自定义的方言类全限定名即可:

# 原配置
# hibernate.dialect = org.hibernate.dialect.Oracle12cDialect
# 替换为你自定义方言的全路径
hibernate.dialect = com.yourpackage.config.CustomOracle12cDialect

方案2:通过配置直接指定LimitHandler(无需新增类,适合支持对应配置的版本)

如果你的Hibernate版本支持hibernate.query.limit_handler配置项,直接在配置文件中添加以下配置即可,不需要自定义方言:

hibernate.query.limit_handler = org.hibernate.dialect.pagination.SQL2008StandardLimitHandler

方案3:修改业务查询逻辑(适合不想修改框架配置的场景)

将排序用到的userAreaName字段显式加入查询的SELECT列表,再提取结果中的User实体即可满足Oracle的语法要求:

// 省略原有构造Criteria的逻辑
criteriaquery.multiselect(user, functionalArea.get("userAreaName"));
TypedQuery<Object[]> createQuery = entitymanager.createQuery(criteriaquery);
// 处理结果,取第一个元素即为User实体
List<User> content = createQuery.setFirstResult((int) pageable.getOffset())
        .setMaxResults(pageable.getPageSize())
        .getResultList()
        .stream()
        .map(arr -> (User) arr[0])
        .toList();

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 02:00:04