`
sgl124764903
  • 浏览: 174682 次
  • 性别: Icon_minigender_1
  • 来自: 邯郸
社区版块
存档分类
最新评论

使ibatis支持hibernate式的物理分页(1)

阅读更多

一 直以来ibatis的分页都是通过滚动ResultSet实现的,应该算是逻辑分页吧。逻辑分页虽然能很干净地独立于特定数据库,但效率在多数情况下不及 特定数据库支持的物理分页,而hibernate的分页则是直接组装sql,充分利用了特定数据库的分页机制,效率相对较高。本文讲述的就是如何在不重新 编译ibatis源码的前提下,为ibatis引入hibernate式的物理分页机制。

基本思路就是找到ibatis执行sql的地方, 截获sql并重新组装sql。通过分析ibatis源码知道,最终负责执行sql的类是 com.ibatis.sqlmap.engine.execution.SqlExecutor,此类没有实现任何接口,这多少有点遗憾,因为接口是相 对稳定契约,非大的版本更新,接口一般是不会变的,而类就相对易变一些,所以这里的代码只能保证对当前版本(2.1.7)的ibatis有效。下面是 SqlExecutor执行查询的方法:

  /**
   * Long form of the method to execute a query
   *
   * 
@param request - the request scope
   * 
@param conn - the database connection
   * 
@param sql - the SQL statement to execute
   * 
@param parameters - the parameters for the statement
   * 
@param skipResults - the number of results to skip
   * 
@param maxResults - the maximum number of results to return
   * 
@param callback - the row handler for the query
   *
   * 
@throws SQLException - if the query fails
   
*/
  
public void executeQuery(RequestScope request, Connection conn, String sql, Object[] parameters,
                           
int skipResults, int maxResults, RowHandlerCallback callback)
      
throws SQLException {
    ErrorContext errorContext 
= request.getErrorContext();
    errorContext.setActivity(
"executing query");
    errorContext.setObjectId(sql);

    PreparedStatement ps 
= null;
    ResultSet rs 
= null;

    
try {
      errorContext.setMoreInfo(
"Check the SQL Statement (preparation failed).");

      Integer rsType 
= request.getStatement().getResultSetType();
      
if (rsType != null) {
        ps 
= conn.prepareStatement(sql, rsType.intValue(), ResultSet.CONCUR_READ_ONLY);
      } 
else {
        ps 
= conn.prepareStatement(sql);
      }

      Integer fetchSize 
= request.getStatement().getFetchSize();
      
if (fetchSize != null) {
        ps.setFetchSize(fetchSize.intValue());
      }

      errorContext.setMoreInfo(
"Check the parameters (set parameters failed).");
      request.getParameterMap().setParameters(request, ps, parameters);

      errorContext.setMoreInfo(
"Check the statement (query failed).");

      ps.execute();
      rs 
= getFirstResultSet(ps);

      
if (rs != null) {
        errorContext.setMoreInfo(
"Check the results (failed to retrieve results).");
        handleResults(request, rs, skipResults, maxResults, callback);
      }

      
// clear out remaining results
      while (ps.getMoreResults());

    } 
finally {
      
try {
        closeResultSet(rs);
      } 
finally {
        closeStatement(ps);
      }
    }

  }

 

其 中handleResults(request, rs, skipResults, maxResults, callback)一句用于处理分页,其实此时查询已经执行完毕,可以不必关心handleResults方法,但为清楚起见,下面来看看 handleResults的实现:

private void handleResults(RequestScope request, ResultSet rs, int skipResults, int maxResults, RowHandlerCallback callback) throws SQLException {
    
try {
      request.setResultSet(rs);
      ResultMap resultMap 
= request.getResultMap();
      
if (resultMap != null) {
        
// Skip Results
        if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {
          
if (skipResults > 0) {
            rs.absolute(skipResults);
          }
        } 
else {
          
for (int i = 0; i < skipResults; i++) {
            
if (!rs.next()) {
              
break;
            }
          }
        }

        
// Get Results
        int resultsFetched = 0;
        
while ((maxResults == SqlExecutor.NO_MAXIMUM_RESULTS || resultsFetched < maxResults) && rs.next()) {
          Object[] columnValues 
= resultMap.resolveSubMap(request, rs).getResults(request, rs);
          callback.handleResultObject(request, columnValues, rs);
          resultsFetched
++;
        }
      }
    } 
finally {
      request.setResultSet(
null);
    }
  }

 

此 处优先使用的是ResultSet的absolute方法定位记录,是否支持absolute取决于具体数据库驱动,但一般当前版本的数据库都支持该方 法,如果不支持则逐条跳过前面的记录。由此可以看出如果数据库支持absolute,则ibatis内置的分页策略与特定数据库的物理分页效率差距就在于 物理分页查询与不分页查询在数据库中的执行效率的差距了。因为查询执行后读取数据前数据库并未把结果全部返回到内存,所以本身在存储占用上应该差距不大, 如果都使用索引,估计执行速度也差不太多。

分享到:
评论

相关推荐

    对IBatis分页的改进,使ibatis支持hibernate式的物理分页

    公司的大部分项目都开始使用IBatis作为O/R Mapping了,但是在使用的过程中也发现了很多不方便和存在...想了很多办法,都没能很好的避免这个问题,无意间在javaeye上看到了《使ibatis支持hibernate式的物理分页》这篇文章,

    对IBatis分页的改进,使ibatis支持hibernate式的物理分页.doc

    总之,通过以上方法,我们可以实现在不修改iBatis源码的前提下,让iBatis支持类似Hibernate的物理分页,提高查询效率,尤其在大数据量的场景下,这种优化尤为关键。不过,需要注意的是,不同的数据库系统对物理分页...

    spring-ibatis-ext-plugin.1.0.0 扩展ibaits原生SQL

    本文讲述的就是如何在不重新编译ibatis源码的前提下,为ibatis引入hibernate式的物理分页机制。 基本思路就是找到ibatis执行sql的地方,截获sql并重新组装sql。通过分析ibatis源码知道,最终负责执行sql的类是 ...

    利用Mybatis的动态SQL实现物理分页.pdf

    【标题】:“利用Mybatis的动态SQL实现物理分页” 【描述】:本文主要探讨了在实际项目中如何利用Mybatis的动态SQL功能来解决大数据量下的物理分页问题,以避免内存溢出。 【标签】:“SQL 数据库 数据处理 参考...

    Hitis-src-1.0.jar

    (5)在ibatis中,想做物理分页,你必须在写一个列表sql,还要写一个90%一样的总页数的sql,不仅如此,你还要在列表sql外包上一层分页sql代码,你不觉得麻烦吗?但Hitis,直接返回给你实际执行的sql和paramters数组,...

    Hitis V1.2.2

    (5)在ibatis中,想做物理分页,你必须在写一个列表sql,还要写一个90%一样的总页数的sql,不仅如此,你还要在列表sql外包上一层分页sql代码,你不觉得麻烦吗?但Hitis,直接返回给你实际执行的sql和paramters数组,...

    Hitis V1.1

    (5)在ibatis中,想做物理分页,你必须在写一个列表sql,还要写一个90%一样的总页数的sql,不仅如此,你还要在列表sql外包上一层分页sql代码,你不觉得麻烦吗?但Hitis,直接返回给你实际执行的sql和paramters数组,...

    Hitis V1.2.1

    (5)在ibatis中,想做物理分页,你必须在写一个列表sql,还要写一个90%一样的总页数的sql,不仅如此,你还要在列表sql外包上一层分页sql代码,你不觉得麻烦吗?但Hitis,直接返回给你实际执行的sql和paramters数组,...

    Hitis V1.1.1

    (5)在ibatis中,想做物理分页,你必须在写一个列表sql,还要写一个90%一样的总页数的sql,不仅如此,你还要在列表sql外包上一层分页sql代码,你不觉得麻烦吗?但Hitis,直接返回给你实际执行的sql和paramters数组,...

    Hitis V1.2

    (5)在ibatis中,想做物理分页,你必须在写一个列表sql,还要写一个90%一样的总页数的sql,不仅如此,你还要在列表sql外包上一层分页sql代码,你不觉得麻烦吗?但Hitis,直接返回给你实际执行的sql和paramters数组,...

    java必备知识点大全.pdf

    Hibernate、Ibatis、Jdbc三者的区别:Hibernate和Ibatis都是JDBC的封装框架,但Hibernate是全自动的ORM映射,而Ibatis是半自动的。 Hibernate的运行原理:Hibernate通过映射关系将Java对象和数据库表进行映射。 ...

    springmybatis

    以前曾经用过ibatis,这是mybatis的前身,当时在做项目时,感觉很不错,比hibernate灵活。性能也比hibernate好。而且也比较轻量级,因为当时在项目中,没来的及做很很多笔记。后来项目结束了,我也没写总结文档。已经...

    自整理Java关于基础和框架的面试题

    ##### Hibernate、Ibatis、Jdbc三者的区别 - **Hibernate**:全ORM框架,简化了数据持久化操作。 - **iBatis**(MyBatis):半ORM框架,需要手动编写SQL语句。 - **JDBC**:直接使用SQL语句进行数据库操作。 ##### ...

    java面试知识

    ##### Hibernate、Ibatis、Jdbc三者的区别 - **Hibernate**:全ORM解决方案,自动管理对象的生命周期。 - **MyBatis (原Ibatis)**:半ORM框架,提供动态SQL支持。 - **JDBC**:直接与数据库交互,灵活性高但编码...

Global site tag (gtag.js) - Google Analytics