Mybatis源码分析_struts源码

Mybatis源码分析_struts源码Mybatis提供了一个简单的逻辑分页类RowBounds,其原理类似于在内存中做了一个分页,不是数据库层面的分页,性能不算好,谨慎使用一.RowBounds源码分析1RowBounds源码:/***Copyright2009-2017theoriginalauthororauthors.**LicensedundertheApacheLicense,Version2.0(the”License”);*youmaynot.

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE使用 1年只要46元 售后保障 童叟无欺

Mybatis提供了一个简单的逻辑分页类RowBounds,其原理类似于在内存中做了一个分页,不是数据库层面的分页,性能不算好,谨慎使用

一. RowBounds源码分析

1 RowBounds源码:

/** * Copyright 2009-2017 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */
package org.apache.ibatis.session;

/** * @author Clinton Begin */
public class RowBounds { 
   

  public static final int NO_ROW_OFFSET = 0;
  public static final int NO_ROW_LIMIT = Integer.MAX_VALUE;
  public static final RowBounds DEFAULT = new RowBounds();

  private final int offset;
  private final int limit;

  public RowBounds() { 
   
    this.offset = NO_ROW_OFFSET;
    this.limit = NO_ROW_LIMIT;
  }

  public RowBounds(int offset, int limit) { 
   
    this.offset = offset;
    this.limit = limit;
  }

  public int getOffset() { 
   
    return offset;
  }

  public int getLimit() { 
   
    return limit;
  }

}

2 SqlSession类

  /** * Retrieve a list of mapped objects from the statement key and parameter, * within the specified row bounds. * @param <E> the returned list element type * @param statement Unique identifier matching the statement to use. * @param parameter A parameter object to pass to the statement. * @param rowBounds Bounds to limit object retrieval * @return List of mapped object */
  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);

我们发现SqlSession类中有一个重载的函数SelectList,其第三个参数是RowBounds
如下这样使用实现分页功能:

 SqlSession session = sqlSessionFactory.openSession();
 Map<String, String> sqlMap = new HashMap<>();
 sqlMap.put("sql", "select * from test_data");
 List<Map> result = null;
 String method = "com.iscas.biz.mp.mapper.DynamicMapper.dynamicSelect";
 RowBounds rowBounds = new RowBounds(600000, 20);
 result = session.selectList(method, sqlMap, rowBounds);

3 查看DefaultSqlSession中selectList的实现

 @Override
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { 
   
    try { 
   
      MappedStatement ms = configuration.getMappedStatement(statement);
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) { 
   
      throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e);
    } finally { 
   
      ErrorContext.instance().reset();
    }
  }

4 查看BaseExecutor中query的实现

@Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException { 
   
    BoundSql boundSql = ms.getBoundSql(parameter);
    CacheKey key = createCacheKey(ms, parameter, rowBounds, boundSql);
    return query(ms, parameter, rowBounds, resultHandler, key, boundSql);
  }

5 查看BaseExecutor中query重载实现

 @Override
  public <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { 
   
    ErrorContext.instance().resource(ms.getResource()).activity("executing a query").object(ms.getId());
    if (closed) { 
   
      throw new ExecutorException("Executor was closed.");
    }
    if (queryStack == 0 && ms.isFlushCacheRequired()) { 
   
      clearLocalCache();
    }
    List<E> list;
    try { 
   
      queryStack++;
      list = resultHandler == null ? (List<E>) localCache.getObject(key) : null;
      if (list != null) { 
   
        handleLocallyCachedOutputParameters(ms, key, parameter, boundSql);
      } else { 
   
        list = queryFromDatabase(ms, parameter, rowBounds, resultHandler, key, boundSql);
      }
    } finally { 
   
      queryStack--;
    }
    if (queryStack == 0) { 
   
      for (DeferredLoad deferredLoad : deferredLoads) { 
   
        deferredLoad.load();
      }
      // issue #601
      deferredLoads.clear();
      if (configuration.getLocalCacheScope() == LocalCacheScope.STATEMENT) { 
   
        // issue #482
        clearLocalCache();
      }
    }
    return list;
  }

6 查看BaseExecutor中queryFromDatabase实现

  private <E> List<E> queryFromDatabase(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey key, BoundSql boundSql) throws SQLException { 
   
    List<E> list;
    localCache.putObject(key, EXECUTION_PLACEHOLDER);
    try { 
   
      list = doQuery(ms, parameter, rowBounds, resultHandler, boundSql);
    } finally { 
   
      localCache.removeObject(key);
    }
    localCache.putObject(key, list);
    if (ms.getStatementType() == StatementType.CALLABLE) { 
   
      localOutputParameterCache.putObject(key, parameter);
    }
    return list;
  }

7 查看BaseExecutor中doQuery的实现

@Override
  public <E> List<E> doQuery(MappedStatement ms, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql)
      throws SQLException { 
   
    Statement stmt = null;
    try { 
   
      flushStatements();
      Configuration configuration = ms.getConfiguration();
      StatementHandler handler = configuration.newStatementHandler(wrapper, ms, parameterObject, rowBounds, resultHandler, boundSql);
      Connection connection = getConnection(ms.getStatementLog());
      stmt = handler.prepare(connection, transaction.getTimeout());
      handler.parameterize(stmt);
      return handler.query(stmt, resultHandler);
    } finally { 
   
      closeStatement(stmt);
    }
  }

8 查看Configuration中newStatementHandler的实现

  public StatementHandler newStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 
   
    StatementHandler statementHandler = new RoutingStatementHandler(executor, mappedStatement, parameterObject, rowBounds, resultHandler, boundSql);
    statementHandler = (StatementHandler) interceptorChain.pluginAll(statementHandler);
    return statementHandler;
  }

9 查看RoutingStatementHandler的构造器

  public RoutingStatementHandler(Executor executor, MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 
   

    switch (ms.getStatementType()) { 
   
      case STATEMENT:
        delegate = new SimpleStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case PREPARED:
        delegate = new PreparedStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      case CALLABLE:
        delegate = new CallableStatementHandler(executor, ms, parameter, rowBounds, resultHandler, boundSql);
        break;
      default:
        throw new ExecutorException("Unknown statement type: " + ms.getStatementType());
    }

  }

10 查看SimpleStatementHandler的构造器

public SimpleStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 
   
    super(executor, mappedStatement, parameter, rowBounds, resultHandler, boundSql);
  }

11 查看BaseStatementHandler的构造器

protected BaseStatementHandler(Executor executor, MappedStatement mappedStatement, Object parameterObject, RowBounds rowBounds, ResultHandler resultHandler, BoundSql boundSql) { 
   
    this.configuration = mappedStatement.getConfiguration();
    this.executor = executor;
    this.mappedStatement = mappedStatement;
    this.rowBounds = rowBounds;

    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.objectFactory = configuration.getObjectFactory();

    if (boundSql == null) { 
    // issue #435, get the key before calculating the statement
      generateKeys(parameterObject);
      boundSql = mappedStatement.getBoundSql(parameterObject);
    }

    this.boundSql = boundSql;

    this.parameterHandler = configuration.newParameterHandler(mappedStatement, parameterObject, boundSql);
    this.resultSetHandler = configuration.newResultSetHandler(executor, mappedStatement, rowBounds, parameterHandler, resultHandler, boundSql);
  }

12 查看Configuration中newResultSetHandler的实现

  public ResultSetHandler newResultSetHandler(Executor executor, MappedStatement mappedStatement, RowBounds rowBounds, ParameterHandler parameterHandler,
      ResultHandler resultHandler, BoundSql boundSql) { 
   
    ResultSetHandler resultSetHandler = new DefaultResultSetHandler(executor, mappedStatement, parameterHandler, resultHandler, boundSql, rowBounds);
    resultSetHandler = (ResultSetHandler) interceptorChain.pluginAll(resultSetHandler);
    return resultSetHandler;
  }

13 查看DefaultResultSetHandler构造器

  public DefaultResultSetHandler(Executor executor, MappedStatement mappedStatement, ParameterHandler parameterHandler, ResultHandler<?> resultHandler, BoundSql boundSql,
                                 RowBounds rowBounds) { 
   
    this.executor = executor;
    this.configuration = mappedStatement.getConfiguration();
    this.mappedStatement = mappedStatement;
    this.rowBounds = rowBounds;
    this.parameterHandler = parameterHandler;
    this.boundSql = boundSql;
    this.typeHandlerRegistry = configuration.getTypeHandlerRegistry();
    this.objectFactory = configuration.getObjectFactory();
    this.reflectorFactory = configuration.getReflectorFactory();
    this.resultHandler = resultHandler;
  }

重点来了,DefaultResultSetHandler是JDBC结果集的处理类,此类中有如下代码:

private void handleResultSet(ResultSetWrapper rsw, ResultMap resultMap, List<Object> multipleResults, ResultMapping parentMapping) throws SQLException { 
   
    try { 
   
      if (parentMapping != null) { 
   
        handleRowValues(rsw, resultMap, null, RowBounds.DEFAULT, parentMapping);
      } else { 
   
        if (resultHandler == null) { 
   
          DefaultResultHandler defaultResultHandler = new DefaultResultHandler(objectFactory);
          handleRowValues(rsw, resultMap, defaultResultHandler, rowBounds, null);
          multipleResults.add(defaultResultHandler.getResultList());
        } else { 
   
          handleRowValues(rsw, resultMap, resultHandler, rowBounds, null);
        }
      }
    } finally { 
   
      // issue #228 (close resultsets)
      closeResultSet(rsw.getResultSet());
    }
  }
 //
  // HANDLE ROWS FOR SIMPLE RESULTMAP
  //

  public void handleRowValues(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping) throws SQLException { 
   
    if (resultMap.hasNestedResultMaps()) { 
   
      ensureNoRowBounds();
      checkResultHandler();
      handleRowValuesForNestedResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    } else { 
   
      handleRowValuesForSimpleResultMap(rsw, resultMap, resultHandler, rowBounds, parentMapping);
    }
  }
  private void handleRowValuesForSimpleResultMap(ResultSetWrapper rsw, ResultMap resultMap, ResultHandler<?> resultHandler, RowBounds rowBounds, ResultMapping parentMapping)
      throws SQLException { 
   
    DefaultResultContext<Object> resultContext = new DefaultResultContext<>();
    ResultSet resultSet = rsw.getResultSet();
    skipRows(resultSet, rowBounds);
    while (shouldProcessMoreRows(resultContext, rowBounds) && !resultSet.isClosed() && resultSet.next()) { 
   
      ResultMap discriminatedResultMap = resolveDiscriminatedResultMap(resultSet, resultMap, null);
      Object rowValue = getRowValue(rsw, discriminatedResultMap, null);
      storeObject(resultHandler, resultContext, rowValue, parentMapping, resultSet);
    }
  }
    private void skipRows(ResultSet rs, RowBounds rowBounds) throws SQLException { 
   
    if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) { 
   
      if (rowBounds.getOffset() != RowBounds.NO_ROW_OFFSET) { 
   
        rs.absolute(rowBounds.getOffset());
      }
    } else { 
   
      for (int i = 0; i < rowBounds.getOffset(); i++) { 
   
        if (!rs.next()) { 
   
          break;
        }
      }
    }
  }

其中skipRows是此种分页方式的灵魂,根据RowBounds中的offSet偏移量,使ResultSet的游标向下移动若干,便实现了逻辑分页。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/190789.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 史蒂芬周博客地址[通俗易懂]

    史蒂芬周博客地址[通俗易懂]http://www.sdifen.com/

  • 第二篇 FastAI数据准备「建议收藏」

    第二篇 FastAI数据准备「建议收藏」一、FastAI代码组织结构(文档链接)FastAI库主要涉及神经网络在如下四个领域的应用:collab(协同滤波问题)、tabular(结构化数据或者说表格数据处理)、text(自然语言处理)、vision(机器视觉)。对每一领域(除了collab),其下又会按照如下结构组织代码:(1)data:定义了模型所需的数据集类。(2)transform:数据预处理(如对图像数据的图像…

  • leetcode – Missing Ranges

    leetcode – Missing Ranges

  • javaweb转发和重定向的区别_servlet转发和重定向

    javaweb转发和重定向的区别_servlet转发和重定向客户首先发送一个请求到服务器端,服务器端发现匹配的servlet,并指定它去执行,当这个servlet执行完之后,它要调用getRequestDispacther()方法,把请求转发给指定的student_list.jsp,整个流程都是在服务器端完成的,而且是在同一个请求里面完成的,因此servlet和jsp共享的是同一个request,在servlet里面放的所有东西,在student_list中都能取出来,因此,student_list能把结果getAttribute()出来,getAttribute(

  • 快捷方式图标显示不正常_win10快捷方式不显示图标

    快捷方式图标显示不正常_win10快捷方式不显示图标win10系统的电脑近期遇到一个问题,那就是桌面上或者某磁盘中文件夹的程序快捷方式图标丢失显示异常,部分程序为一个白纸图标,不显示原本的程序图标,但是这些软件或者游戏的快捷方式能正常打开。那么游戏、软件等应用程序快捷方式不显示图标怎么办?下面装机之家分享一下Win10快捷方式图标变白纸解决方法。原因分析:在Win10系统中,首次对图标进行显示,为了加速图标的显示,之后系统会对图标进行缓存,如果缓存…

    2022年10月18日
  • mysql 组合索引 前缀_Mysql中的联合索引、前缀索引、覆盖索引[通俗易懂]

    mysql 组合索引 前缀_Mysql中的联合索引、前缀索引、覆盖索引[通俗易懂]索引索引是一种特殊的文件,它们包含着对数据表里所有记录的引用指针。更通俗的说,数据库索引好比是一本书前面的目录,能加快数据库的查询速度。联合索引又名复合索引,由两个或多个列的索引。它规定了mysql从左到右地使用索引字段,对字段的顺序有一定要求。一个查询可以只使用索引中的一部分,更准确地说是最左侧部分(最左优先)。如索引是keyindex(a,b,c).可以支持a|a,b|a,b,c…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号