添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

一、原因分析:
1:当我们使用hibernate的NativeQuery进行分页时,底层会采用limit或rownum,而采用哪种分页方式是有由不同数据库的方言决定的,下面将讲解h2的oracle模式下使用NativeQuery进行分页时报错问题解决org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [SELECT * limit ?]; nested exception is org.hibernate.exception.SQLGrammarException: could not prepare statement
我们会发现h2的oracle模式下采用的却是limit方式进行分页,但是使用limit进行分页又会报错
2:h2分页方式
打开h2的方言类H2Dialect,可以发现h2的分页方式采用的是limit
在这里插入图片描述
3:oracle分页方式
根据不同oracle版本打开oracle的方言类
在这里插入图片描述
我们会发现oracle的底层是采用的rownum进行分页
在这里插入图片描述
二、问题解决
1:由于我们现在只解决分页的问题,这里我们创建一个自定义方言类TestH2Dialect,继承于H2Dialect
在这里插入图片描述
2:有于我们自定义方言类继承于H2Dialect,所以我们不需要关注其他方言问题,我们只需要重写分页方法,就可以解决上述问题,这里我们已oracle12为例
创建TestH2Dialect自定义方言

public class TestH2Dialect extends H2Dialect {
    private static final TestOracle12LimitHandler LIMIT_HANDLER = new TestOracle12LimitHandler() ;
    @Override
    public LimitHandler getLimitHandler() {
        return LIMIT_HANDLER;

创建oracle分页处理类

public class TestOracle12LimitHandler extends AbstractLimitHandler {
    public boolean bindLimitParametersInReverseOrder;
    public boolean useMaxForLimit;
    public static final TestOracle12LimitHandler INSTANCE = new TestOracle12LimitHandler();
    TestOracle12LimitHandler() {
    @Override
    public String processSql(String sql, RowSelection selection) {
        boolean hasFirstRow = LimitHelper.hasFirstRow(selection);
        boolean hasMaxRows = LimitHelper.hasMaxRows(selection);
        return !hasMaxRows ? sql : this.processSql(sql, this.getForUpdateIndex(sql), hasFirstRow);
    @Override
    public String processSql(String sql, QueryParameters queryParameters) {
        RowSelection selection = queryParameters.getRowSelection();
        boolean hasFirstRow = LimitHelper.hasFirstRow(selection);
        boolean hasMaxRows = LimitHelper.hasMaxRows(selection);
        if (!hasMaxRows) {
            return sql;
        } else {
            sql = sql.trim();
            LockOptions lockOptions = queryParameters.getLockOptions();
            if (lockOptions != null) {
                LockMode lockMode = lockOptions.getLockMode();
                switch(lockMode) {
                    case UPGRADE:
                    case PESSIMISTIC_READ:
                    case PESSIMISTIC_WRITE:
                    case UPGRADE_NOWAIT:
                    case FORCE:
                    case PESSIMISTIC_FORCE_INCREMENT:
                    case UPGRADE_SKIPLOCKED:
                        return this.processSql(sql, selection);
                    default:
                        return this.processSqlOffsetFetch(sql, hasFirstRow);
            } else {
                return this.processSqlOffsetFetch(sql, hasFirstRow);
    private String processSqlOffsetFetch(String sql, boolean hasFirstRow) {
        int forUpdateLastIndex = this.getForUpdateIndex(sql);
        if (forUpdateLastIndex > -1) {
            return this.processSql(sql, forUpdateLastIndex, hasFirstRow);
        } else {
            this.bindLimitParametersInReverseOrder = false;
            this.useMaxForLimit = false;
            String offsetFetchString;
            if (hasFirstRow) {
                offsetFetchString = " offset ? rows fetch next ? rows only";
            } else {
                offsetFetchString = " fetch first ? rows only";
            int offsetFetchLength = sql.length() + offsetFetchString.length();
            return (new StringBuilder(offsetFetchLength)).append(sql).append(offsetFetchString).toString();
    private String processSql(String sql, int forUpdateIndex, boolean hasFirstRow) {
        this.bindLimitParametersInReverseOrder = true;
        this.useMaxForLimit = true;
        String forUpdateClause = null;
        boolean isForUpdate = false;
        if (forUpdateIndex > -1) {
            forUpdateClause = sql.substring(forUpdateIndex);
            sql = sql.substring(0, forUpdateIndex - 1);
            isForUpdate = true;
        int forUpdateClauseLength;
        if (forUpdateClause == null) {
            forUpdateClauseLength = 0;
        } else {
            forUpdateClauseLength = forUpdateClause.length() + 1;
        StringBuilder pagingSelect;
        if (hasFirstRow) {
            pagingSelect = new StringBuilder(sql.length() + forUpdateClauseLength + 98);
            pagingSelect.append("select * from ( select row_.*, rownum rownum_ from ( ");
            pagingSelect.append(sql);
            pagingSelect.append(" ) row_ where rownum <= ?) where rownum_ > ?");
        } else {
            pagingSelect = new StringBuilder(sql.length() + forUpdateClauseLength + 37);
            pagingSelect.append("select * from ( ");
            pagingSelect.append(sql);
            pagingSelect.append(" ) where rownum <= ?");
        if (isForUpdate) {
            pagingSelect.append(" ");
            pagingSelect.append(forUpdateClause);
        return pagingSelect.toString();
    private int getForUpdateIndex(String sql) {
        int forUpdateLastIndex = sql.toLowerCase(Locale.ROOT).lastIndexOf("for update");
        int lastIndexOfQuote = sql.lastIndexOf("'");
        if (forUpdateLastIndex > -1) {
            if (lastIndexOfQuote == -1) {
                return forUpdateLastIndex;
            } else {
                return lastIndexOfQuote > forUpdateLastIndex ? -1 : forUpdateLastIndex;
        } else {
            return forUpdateLastIndex;
    @Override
    public final boolean supportsLimit() {
        return true;
    @Override
    public boolean bindLimitParametersInReverseOrder() {
        return this.bindLimitParametersInReverseOrder;
    @Override
    public boolean useMaxForLimit() {
        return this.useMaxForLimit;

3、修改配置文件中采用的方言类
在这里插入图片描述
改成
在这里插入图片描述
三、总结
如果后续遇到其他方言问题,可采用同样的方式解决

h2内存数据库oracle模式,分页报错rg.springframework.dao.InvalidDataAccessResourceUsageException: could not prepar 当我们使用hibernate的NativeQuery进行分页时,底层会采用limit或rownum,而采用哪种分页方式是有由不同数据库的方言决定的,下面将讲解h2的oracle模式下使用NativeQuery进行分页时报错问题解决org.springframework.dao.InvalidDataAccessResourceUsageException: could not prepare statement; SQL [SELECT * limit ?]; nested excep......
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet 问题原因: 这个错误是由无法找到数据库与实体类对应的字段导致异常的: 在控制台看见:突然想起mysql好像是不区分大
这里写自定义目录标题解决办法新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants创建一个自定义列表如何创建一个注脚注释也是必不可少的KaTeX数学公式新的甘特图功能,丰富你的文章UML 图表FLowchart流程图导出与导入导出导入 org.springframework.dao.InvalidDataAccessResourceUsageException: could no
springboot报错org.springframework.dao.InvalidDataAccessResourceUsageException:
org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; 1.表与字段没有对应起来 2.数据库连接池配置方言与数据库不匹配 //oracle数据库方言 hibernate.dialect=org.hibernate.dialect.Oracle10gD... h2内存数据库oracle模式,分页报错rg.springframework.dao.InvalidDataAccessResourceUsageException: could not prepar Error creating bean with name 'org.springframework.web.servlet.mvc.method.annotation.RequestMappingH H2数据库关键字导致org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL 小小越做大牛: 有用,谢谢。 H2数据库关键字导致org.hibernate.tool.schema.spi.CommandAcceptanceException: Error executing DDL CSDN-Ada助手: 推荐 Java 技能树:https://edu.csdn.net/skill/java?utm_source=AI_act_java