iBatis分页

最近在学习iBatis的分页功能,iBatis默认的分页是采用游标滚动的方式来实现的,这种方式在大数据量的情况下便会OOM了,因此一般都采用手写分页SQL语句使用数据库物理分页方式实现,参考了网上很多网友所写的如何实现像hibernate一样使用方言的方式来实现分页功能,基本上千篇一律都是继承com.ibatis.sqlmap.engine.execution.SqlExecutor类然后在spring中进行注入等等,操作复杂编码甚多,方法不可取。 

    另外还有些是修改iBatis的jar包来实现,本人觉得这种方法更不可取。 
    基于网友们的思想,自己实现了另一种方法,不用修改源码,不用在spring中做任何配置即可实现物理分页功能: 
条件 
    1、JVM类的加载是通过Class.forName(String cls)来实现,根据这个原理可以自己写一个与com.ibatis.sqlmap.engine.execution.SqlExecutor同名类; 
    2、java web类的加载顺序是:首先是web容器的相关类与jar包,然后是web工程下面WEB-INF/classes/下的所有类,最后才是WEB-INF/lib下的所有jar包; 
    有了以上的先决条件就好办了,可以在你的项目src目录下建包com.ibatis.sqlmap.engine.execution,然后在此包下建类SqlExecutor,然后把iBatis包下的这个类的源码复制进来后做小小改动,原来的executeQuery方法改成私有、换名,换成什么名称随便,然后新建一个公有的executeQuery方法,分页功能就在这个方法体内实现; 
这样一来,web容器首会找到WEB-INF/classes下的com.ibatis.sqlmap.engine.execution.SqlExecutor这个类,因而会忽略掉在ibatis包中的这个类,即实现了自定义的分页功能,又不用去破坏ibatis的包; 
    还有一点,也可以将自定义的这个类打成jar包放到lib中去,不过这时就要注意了,jar包的名称一定要在ibatis包的名称之前,也就是说ibatis-2.3.4.726.jar,那么这个jar就可以写成ibatis-2.3.4.725.jar,或者字母在ibatis这几个字母之前,这样才能正确加载自己写的那个类。 
贴上代码: 
SqlExecutor.java 
Java代码   收藏代码
  1. /* 
  2.  *  Copyright 2004 Clinton Begin 
  3.  * 
  4.  *  Licensed under the Apache License, Version 2.0 (the "License"); 
  5.  *  you may not use this file except in compliance with the License. 
  6.  *  You may obtain a copy of the License at 
  7.  * 
  8.  *      http://www.apache.org/licenses/LICENSE-2.0 
  9.  * 
  10.  *  Unless required by applicable law or agreed to in writing, software 
  11.  *  distributed under the License is distributed on an "AS IS" BASIS, 
  12.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
  13.  *  See the License for the specific language governing permissions and 
  14.  *  limitations under the License. 
  15.  */  
  16. package com.ibatis.sqlmap.engine.execution;  
  17.   
  18. import java.sql.BatchUpdateException;  
  19. import java.sql.CallableStatement;  
  20. import java.sql.Connection;  
  21. import java.sql.PreparedStatement;  
  22. import java.sql.ResultSet;  
  23. import java.sql.SQLException;  
  24. import java.sql.Statement;  
  25. import java.sql.Types;  
  26. import java.util.ArrayList;  
  27. import java.util.List;  
  28.   
  29. import org.apache.commons.logging.Log;  
  30. import org.apache.commons.logging.LogFactory;  
  31.   
  32. import com.ibatis.sqlmap.engine.impl.SqlMapClientImpl;  
  33. import com.ibatis.sqlmap.engine.impl.SqlMapExecutorDelegate;  
  34. import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;  
  35. import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMapping;  
  36. import com.ibatis.sqlmap.engine.mapping.result.ResultMap;  
  37. import com.ibatis.sqlmap.engine.mapping.result.ResultObjectFactoryUtil;  
  38. import com.ibatis.sqlmap.engine.mapping.statement.DefaultRowHandler;  
  39. import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;  
  40. import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;  
  41. import com.ibatis.sqlmap.engine.scope.ErrorContext;  
  42. import com.ibatis.sqlmap.engine.scope.SessionScope;  
  43. import com.ibatis.sqlmap.engine.scope.StatementScope;  
  44.   
  45. /** 
  46.  * Class responsible for executing the SQL 
  47.  */  
  48. @SuppressWarnings ("unchecked")  
  49. public class SqlExecutor {  
  50.   
  51.     private static final Log log = LogFactory.getLog(SqlExecutor.class);  
  52.     //  
  53.     // Constants  
  54.     //  
  55.     /** 
  56.      * Constant to let us know not to skip anything 
  57.      */  
  58.     public static final int NO_SKIPPED_RESULTS = 0;  
  59.     /** 
  60.      * Constant to let us know to include all records 
  61.      */  
  62.     public static final int NO_MAXIMUM_RESULTS = -999999;  
  63.       
  64.     public SqlExecutor() {  
  65.         log.info("Custom class 'SqlExecutor' Initialization");  
  66.     }  
  67.   
  68.     //  
  69.     // Public Methods  
  70.     //  
  71.   
  72.     /** 
  73.      * Execute an update 
  74.      *  
  75.      * @param statementScope 
  76.      *            - the request scope 
  77.      * @param conn 
  78.      *            - the database connection 
  79.      * @param sql 
  80.      *            - the sql statement to execute 
  81.      * @param parameters 
  82.      *            - the parameters for the sql statement 
  83.      * @return - the number of records changed 
  84.      * @throws SQLException 
  85.      *             - if the update fails 
  86.      */  
  87.     public int executeUpdate(StatementScope statementScope, Connection conn,  
  88.             String sql, Object[] parameters) throws SQLException {  
  89.         ErrorContext errorContext = statementScope.getErrorContext();  
  90.         errorContext.setActivity("executing update");  
  91.         errorContext.setObjectId(sql);  
  92.         PreparedStatement ps = null;  
  93.         setupResultObjectFactory(statementScope);  
  94.         int rows = 0;  
  95.         try {  
  96.             errorContext  
  97.                     .setMoreInfo("Check the SQL Statement (preparation failed).");  
  98.             ps = prepareStatement(statementScope.getSession(), conn, sql);  
  99.             setStatementTimeout(statementScope.getStatement(), ps);  
  100.             errorContext  
  101.                     .setMoreInfo("Check the parameters (set parameters failed).");  
  102.             statementScope.getParameterMap().setParameters(statementScope, ps,  
  103.                     parameters);  
  104.             errorContext.setMoreInfo("Check the statement (update failed).");  
  105.             ps.execute();  
  106.             rows = ps.getUpdateCount();  
  107.         } finally {  
  108.             closeStatement(statementScope.getSession(), ps);  
  109.         }  
  110.         return rows;  
  111.     }  
  112.   
  113.     /** 
  114.      * Adds a statement to a batch 
  115.      *  
  116.      * @param statementScope 
  117.      *            - the request scope 
  118.      * @param conn 
  119.      *            - the database connection 
  120.      * @param sql 
  121.      *            - the sql statement 
  122.      * @param parameters 
  123.      *            - the parameters for the statement 
  124.      * @throws SQLException 
  125.      *             - if the statement fails 
  126.      */  
  127.     public void addBatch(StatementScope statementScope, Connection conn,  
  128.             String sql, Object[] parameters) throws SQLException {  
  129.         Batch batch = (Batch) statementScope.getSession().getBatch();  
  130.         if (batch == null) {  
  131.             batch = new Batch();  
  132.             statementScope.getSession().setBatch(batch);  
  133.         }  
  134.         batch.addBatch(statementScope, conn, sql, parameters);  
  135.     }  
  136.   
  137.     /** 
  138.      * Execute a batch of statements 
  139.      *  
  140.      * @param sessionScope 
  141.      *            - the session scope 
  142.      * @return - the number of rows impacted by the batch 
  143.      * @throws SQLException 
  144.      *             - if a statement fails 
  145.      */  
  146.     public int executeBatch(SessionScope sessionScope) throws SQLException {  
  147.         int rows = 0;  
  148.         Batch batch = (Batch) sessionScope.getBatch();  
  149.         if (batch != null) {  
  150.             try {  
  151.                 rows = batch.executeBatch();  
  152.             } finally {  
  153.                 batch.cleanupBatch(sessionScope);  
  154.             }  
  155.         }  
  156.         return rows;  
  157.     }  
  158.   
  159.     /** 
  160.      * Execute a batch of statements 
  161.      *  
  162.      * @param sessionScope 
  163.      *            - the session scope 
  164.      * @return - a List of BatchResult objects (may be null if no batch has been 
  165.      *         initiated). There will be one BatchResult object in the list for 
  166.      *         each sub-batch executed 
  167.      * @throws SQLException 
  168.      *             if a database access error occurs, or the drive does not 
  169.      *             support batch statements 
  170.      * @throws BatchException 
  171.      *             if the driver throws BatchUpdateException 
  172.      */  
  173.     public List executeBatchDetailed(SessionScope sessionScope)  
  174.             throws SQLException, BatchException {  
  175.         List answer = null;  
  176.         Batch batch = (Batch) sessionScope.getBatch();  
  177.         if (batch != null) {  
  178.             try {  
  179.                 answer = batch.executeBatchDetailed();  
  180.             } finally {  
  181.                 batch.cleanupBatch(sessionScope);  
  182.             }  
  183.         }  
  184.         return answer;  
  185.     }  
  186.   
  187.     /** 
  188.      * Long form of the method to execute a query 
  189.      *  
  190.      * @param statementScope 
  191.      *            - the request scope 
  192.      * @param conn 
  193.      *            - the database connection 
  194.      * @param sql 
  195.      *            - the SQL statement to execute 
  196.      * @param parameters 
  197.      *            - the parameters for the statement 
  198.      * @param skipResults 
  199.      *            - the number of results to skip 
  200.      * @param maxResults 
  201.      *            - the maximum number of results to return 
  202.      * @param callback 
  203.      *            - the row handler for the query 
  204.      * @throws SQLException 
  205.      *             - if the query fails 
  206.      */  
  207. //------------------------------- 分页代码重写(start) ------------------------------------//  
  208.     //重写executeQuery方法,首先判断是否分页查询,分页查询先将分页SQL语句构建,然后执行iBatis默认的查询  
  209.     public void executeQuery(StatementScope statementScope, Connection conn,  
  210.             String sql, Object[] parameters, int skipResults, int maxResults,  
  211.             RowHandlerCallback callback) throws SQLException {  
  212.         //取数据库产品名称  
  213.         String dbName = conn.getMetaData().getDatabaseProductName();  
  214.           
  215.         int len = sql.length();  
  216.           
  217.         //判断是否分页  
  218.         if ((skipResults != NO_SKIPPED_RESULTS || maxResults != NO_MAXIMUM_RESULTS)) {  
  219.             //根据数据库产品名称取对应的分页SQL语句  
  220.             sql = Dialect.getLimitString(dbName, sql, skipResults, maxResults);  
  221.               
  222.             //分页语句是否存在  
  223.             if (sql.length() != len) {  
  224.                 skipResults = NO_SKIPPED_RESULTS;  
  225.                 maxResults = NO_MAXIMUM_RESULTS;  
  226.             }  
  227.         }  
  228.         iBatisExecuteQuery(statementScope, conn, sql, parameters, skipResults,  
  229.                 maxResults, callback);  
  230.     }  
  231.       
  232.     //iBatis包中默认的executeQuery方法  
  233.     private void iBatisExecuteQuery(StatementScope statementScope,  
  234.             Connection conn, String sql, Object[] parameters, int skipResults,  
  235.             int maxResults, RowHandlerCallback callback) throws SQLException {  
  236.         ErrorContext errorContext = statementScope.getErrorContext();  
  237.         errorContext.setActivity("executing query");  
  238.         errorContext.setObjectId(sql);  
  239.         PreparedStatement ps = null;  
  240.         ResultSet rs = null;  
  241.         setupResultObjectFactory(statementScope);  
  242.         try {  
  243.             errorContext  
  244.                     .setMoreInfo("Check the SQL Statement (preparation failed).");  
  245.             Integer rsType = statementScope.getStatement().getResultSetType();  
  246.             if (rsType != null) {  
  247.                 ps = prepareStatement(statementScope.getSession(), conn, sql,  
  248.                         rsType);  
  249.             } else {  
  250.                 ps = prepareStatement(statementScope.getSession(), conn, sql);  
  251.             }  
  252.             setStatementTimeout(statementScope.getStatement(), ps);  
  253.             Integer fetchSize = statementScope.getStatement().getFetchSize();  
  254.             if (fetchSize != null) {  
  255.                 ps.setFetchSize(fetchSize.intValue());  
  256.             }  
  257.             errorContext  
  258.                     .setMoreInfo("Check the parameters (set parameters failed).");  
  259.             statementScope.getParameterMap().setParameters(statementScope, ps,  
  260.                     parameters);  
  261.             errorContext.setMoreInfo("Check the statement (query failed).");  
  262.             ps.execute();  
  263.             errorContext  
  264.                     .setMoreInfo("Check the results (failed to retrieve results).");  
  265.   
  266.             // Begin ResultSet Handling  
  267.             rs = handleMultipleResults(ps, statementScope, skipResults,  
  268.                     maxResults, callback);  
  269.             // End ResultSet Handling  
  270.         } finally {  
  271.             try {  
  272.                 closeResultSet(rs);  
  273.             } finally {  
  274.                 closeStatement(statementScope.getSession(), ps);  
  275.             }  
  276.         }  
  277.     }  
  278. //-------------------- 分页代码重写(end) -------------------------------------//  
  279.     /** 
  280.      * Execute a stored procedure that updates data 
  281.      *  
  282.      * @param statementScope 
  283.      *            - the request scope 
  284.      * @param conn 
  285.      *            - the database connection 
  286.      * @param sql 
  287.      *            - the SQL to call the procedure 
  288.      * @param parameters 
  289.      *            - the parameters for the procedure 
  290.      * @return - the rows impacted by the procedure 
  291.      * @throws SQLException 
  292.      *             - if the procedure fails 
  293.      */  
  294.     public int executeUpdateProcedure(StatementScope statementScope,  
  295.             Connection conn, String sql, Object[] parameters)  
  296.             throws SQLException {  
  297.         ErrorContext errorContext = statementScope.getErrorContext();  
  298.         errorContext.setActivity("executing update procedure");  
  299.         errorContext.setObjectId(sql);  
  300.         CallableStatement cs = null;  
  301.         setupResultObjectFactory(statementScope);  
  302.         int rows = 0;  
  303.         try {  
  304.             errorContext  
  305.                     .setMoreInfo("Check the SQL Statement (preparation failed).");  
  306.             cs = prepareCall(statementScope.getSession(), conn, sql);  
  307.             setStatementTimeout(statementScope.getStatement(), cs);  
  308.             ParameterMap parameterMap = statementScope.getParameterMap();  
  309.             ParameterMapping[] mappings = parameterMap.getParameterMappings();  
  310.             errorContext  
  311.                     .setMoreInfo("Check the output parameters (register output parameters failed).");  
  312.             registerOutputParameters(cs, mappings);  
  313.             errorContext  
  314.                     .setMoreInfo("Check the parameters (set parameters failed).");  
  315.             parameterMap.setParameters(statementScope, cs, parameters);  
  316.             errorContext  
  317.                     .setMoreInfo("Check the statement (update procedure failed).");  
  318.             cs.execute();  
  319.             rows = cs.getUpdateCount();  
  320.             errorContext  
  321.                     .setMoreInfo("Check the output parameters (retrieval of output parameters failed).");  
  322.             retrieveOutputParameters(statementScope, cs, mappings, parameters,  
  323.                     null);  
  324.         } finally {  
  325.             closeStatement(statementScope.getSession(), cs);  
  326.         }  
  327.         return rows;  
  328.     }  
  329.   
  330.     /** 
  331.      * Execute a stored procedure 
  332.      *  
  333.      * @param statementScope 
  334.      *            - the request scope 
  335.      * @param conn 
  336.      *            - the database connection 
  337.      * @param sql 
  338.      *            - the sql to call the procedure 
  339.      * @param parameters 
  340.      *            - the parameters for the procedure 
  341.      * @param skipResults 
  342.      *            - the number of results to skip 
  343.      * @param maxResults 
  344.      *            - the maximum number of results to return 
  345.      * @param callback 
  346.      *            - a row handler for processing the results 
  347.      * @throws SQLException 
  348.      *             - if the procedure fails 
  349.      */  
  350.     public void executeQueryProcedure(StatementScope statementScope,  
  351.             Connection conn, String sql, Object[] parameters, int skipResults,  
  352.             int maxResults, RowHandlerCallback callback) throws SQLException {  
  353.         ErrorContext errorContext = statementScope.getErrorContext();  
  354.         errorContext.setActivity("executing query procedure");  
  355.         errorContext.setObjectId(sql);  
  356.         CallableStatement cs = null;  
  357.         ResultSet rs = null;  
  358.         setupResultObjectFactory(statementScope);  
  359.         try {  
  360.             errorContext  
  361.                     .setMoreInfo("Check the SQL Statement (preparation failed).");  
  362.             Integer rsType = statementScope.getStatement().getResultSetType();  
  363.             if (rsType != null) {  
  364.                 cs = prepareCall(statementScope.getSession(), conn, sql, rsType);  
  365.             } else {  
  366.                 cs = prepareCall(statementScope.getSession(), conn, sql);  
  367.             }  
  368.             setStatementTimeout(statementScope.getStatement(), cs);  
  369.             Integer fetchSize = statementScope.getStatement().getFetchSize();  
  370.             if (fetchSize != null) {  
  371.                 cs.setFetchSize(fetchSize.intValue());  
  372.             }  
  373.             ParameterMap parameterMap = statementScope.getParameterMap();  
  374.             ParameterMapping[] mappings = parameterMap.getParameterMappings();  
  375.             errorContext  
  376.                     .setMoreInfo("Check the output parameters (register output parameters failed).");  
  377.             registerOutputParameters(cs, mappings);  
  378.             errorContext  
  379.                     .setMoreInfo("Check the parameters (set parameters failed).");  
  380.             parameterMap.setParameters(statementScope, cs, parameters);  
  381.             errorContext  
  382.                     .setMoreInfo("Check the statement (update procedure failed).");  
  383.             cs.execute();  
  384.             errorContext  
  385.                     .setMoreInfo("Check the results (failed to retrieve results).");  
  386.   
  387.             // Begin ResultSet Handling  
  388.             rs = handleMultipleResults(cs, statementScope, skipResults,  
  389.                     maxResults, callback);  
  390.             // End ResultSet Handling  
  391.             errorContext  
  392.                     .setMoreInfo("Check the output parameters (retrieval of output parameters failed).");  
  393.             retrieveOutputParameters(statementScope, cs, mappings, parameters,  
  394.                     callback);  
  395.   
  396.         } finally {  
  397.             try {  
  398.                 closeResultSet(rs);  
  399.             } finally {  
  400.                 closeStatement(statementScope.getSession(), cs);  
  401.             }  
  402.         }  
  403.     }  
  404.   
  405.     private ResultSet handleMultipleResults(PreparedStatement ps,  
  406.             StatementScope statementScope, int skipResults, int maxResults,  
  407.             RowHandlerCallback callback) throws SQLException {  
  408.         ResultSet rs;  
  409.         rs = getFirstResultSet(statementScope, ps);  
  410.         if (rs != null) {  
  411.             handleResults(statementScope, rs, skipResults, maxResults, callback);  
  412.         }  
  413.   
  414.         // Multiple ResultSet handling  
  415.         if (callback.getRowHandler() instanceof DefaultRowHandler) {  
  416.             MappedStatement statement = statementScope.getStatement();  
  417.             DefaultRowHandler defaultRowHandler = ((DefaultRowHandler) callback  
  418.                     .getRowHandler());  
  419.             if (statement.hasMultipleResultMaps()) {  
  420.                 List multipleResults = new ArrayList();  
  421.                 multipleResults.add(defaultRowHandler.getList());  
  422.                 ResultMap[] resultMaps = statement.getAdditionalResultMaps();  
  423.                 int i = 0;  
  424.                 while (moveToNextResultsSafely(statementScope, ps)) {  
  425.                     if (i >= resultMaps.length)  
  426.                         break;  
  427.                     ResultMap rm = resultMaps[i];  
  428.                     statementScope.setResultMap(rm);  
  429.                     rs = ps.getResultSet();  
  430.                     DefaultRowHandler rh = new DefaultRowHandler();  
  431.                     handleResults(statementScope, rs, skipResults, maxResults,  
  432.                             new RowHandlerCallback(rm, null, rh));  
  433.                     multipleResults.add(rh.getList());  
  434.                     i++;  
  435.                 }  
  436.                 defaultRowHandler.setList(multipleResults);  
  437.                 statementScope.setResultMap(statement.getResultMap());  
  438.             } else {  
  439.                 while (moveToNextResultsSafely(statementScope, ps))  
  440.                     ;  
  441.             }  
  442.         }  
  443.         // End additional ResultSet handling  
  444.         return rs;  
  445.     }  
  446.   
  447.     private ResultSet getFirstResultSet(StatementScope scope, Statement stmt)  
  448.             throws SQLException {  
  449.         ResultSet rs = null;  
  450.         boolean hasMoreResults = true;  
  451.         while (hasMoreResults) {  
  452.             rs = stmt.getResultSet();  
  453.             if (rs != null) {  
  454.                 break;  
  455.             }  
  456.             hasMoreResults = moveToNextResultsIfPresent(scope, stmt);  
  457.         }  
  458.         return rs;  
  459.     }  
  460.   
  461.     private boolean moveToNextResultsIfPresent(StatementScope scope,  
  462.             Statement stmt) throws SQLException {  
  463.         boolean moreResults;  
  464.         // This is the messed up JDBC approach for determining if there are more  
  465.         // results  
  466.         moreResults = !(((moveToNextResultsSafely(scope, stmt) == false) && (stmt  
  467.                 .getUpdateCount() == -1)));  
  468.         return moreResults;  
  469.     }  
  470.   
  471.     private boolean moveToNextResultsSafely(StatementScope scope, Statement stmt)  
  472.             throws SQLException {  
  473.         if (forceMultipleResultSetSupport(scope)  
  474.                 || stmt.getConnection().getMetaData()  
  475.                         .supportsMultipleResultSets()) {  
  476.             return stmt.getMoreResults();  
  477.         }  
  478.         return false;  
  479.     }  
  480.   
  481.     private boolean forceMultipleResultSetSupport(StatementScope scope) {  
  482.         return ((SqlMapClientImpl) scope.getSession().getSqlMapClient())  
  483.                 .getDelegate().isForceMultipleResultSetSupport();  
  484.     }  
  485.   
  486.     private void handleResults(StatementScope statementScope, ResultSet rs,  
  487.             int skipResults, int maxResults, RowHandlerCallback callback)  
  488.             throws SQLException {  
  489.         try {  
  490.             statementScope.setResultSet(rs);  
  491.             ResultMap resultMap = statementScope.getResultMap();  
  492.             if (resultMap != null) {  
  493.                 // Skip Results  
  494.                 if (rs.getType() != ResultSet.TYPE_FORWARD_ONLY) {  
  495.                     if (skipResults > 0) {  
  496.                         rs.absolute(skipResults);  
  497.                     }  
  498.                 } else {  
  499.                     for (int i = 0; i < skipResults; i++) {  
  500.                         if (!rs.next()) {  
  501.                             return;  
  502.                         }  
  503.                     }  
  504.                 }  
  505.   
  506.                 // Get Results  
  507.                 int resultsFetched = 0;  
  508.                 while ((maxResults == SqlExecutor.NO_MAXIMUM_RESULTS || resultsFetched < maxResults)  
  509.                         && rs.next()) {  
  510.                     Object[] columnValues = resultMap.resolveSubMap(  
  511.                             statementScope, rs).getResults(statementScope, rs);  
  512.                     callback.handleResultObject(statementScope, columnValues,  
  513.                             rs);  
  514.                     resultsFetched++;  
  515.                 }  
  516.             }  
  517.         } finally {  
  518.             statementScope.setResultSet(null);  
  519.         }  
  520.     }  
  521.   
  522.     private void retrieveOutputParameters(StatementScope statementScope,  
  523.             CallableStatement cs, ParameterMapping[] mappings,  
  524.             Object[] parameters, RowHandlerCallback callback)  
  525.             throws SQLException {  
  526.         for (int i = 0; i < mappings.length; i++) {  
  527.             ParameterMapping mapping = ((ParameterMapping) mappings[i]);  
  528.             if (mapping.isOutputAllowed()) {  
  529.                 if ("java.sql.ResultSet".equalsIgnoreCase(mapping  
  530.                         .getJavaTypeName())) {  
  531.                     ResultSet rs = (ResultSet) cs.getObject(i + 1);  
  532.                     ResultMap resultMap;  
  533.                     if (mapping.getResultMapName() == null) {  
  534.                         resultMap = statementScope.getResultMap();  
  535.                         handleOutputParameterResults(statementScope, resultMap,  
  536.                                 rs, callback);  
  537.                     } else {  
  538.                         SqlMapClientImpl client = (SqlMapClientImpl) statementScope  
  539.                                 .getSession().getSqlMapClient();  
  540.                         resultMap = client.getDelegate().getResultMap(  
  541.                                 mapping.getResultMapName());  
  542.                         DefaultRowHandler rowHandler = new DefaultRowHandler();  
  543.                         RowHandlerCallback handlerCallback = new RowHandlerCallback(  
  544.                                 resultMap, null, rowHandler);  
  545.                         handleOutputParameterResults(statementScope, resultMap,  
  546.                                 rs, handlerCallback);  
  547.                         parameters[i] = rowHandler.getList();  
  548.                     }  
  549.                     rs.close();  
  550.                 } else {  
  551.                     parameters[i] = mapping.getTypeHandler().getResult(cs,  
  552.                             i + 1);  
  553.                 }  
  554.             }  
  555.         }  
  556.     }  
  557.   
  558.     private void registerOutputParameters(CallableStatement cs,  
  559.             ParameterMapping[] mappings) throws SQLException {  
  560.         for (int i = 0; i < mappings.length; i++) {  
  561.             ParameterMapping mapping = ((ParameterMapping) mappings[i]);  
  562.             if (mapping.isOutputAllowed()) {  
  563.                 if (null != mapping.getTypeName()  
  564.                         && !mapping.getTypeName().equals("")) { // @added  
  565.                     cs.registerOutParameter(i + 1, mapping.getJdbcType(),  
  566.                             mapping.getTypeName());  
  567.                 } else {  
  568.                     if (mapping.getNumericScale() != null  
  569.                             && (mapping.getJdbcType() == Types.NUMERIC || mapping  
  570.                                     .getJdbcType() == Types.DECIMAL)) {  
  571.                         cs.registerOutParameter(i + 1, mapping.getJdbcType(),  
  572.                                 mapping.getNumericScale().intValue());  
  573.                     } else {  
  574.                         cs.registerOutParameter(i + 1, mapping.getJdbcType());  
  575.                     }  
  576.                 }  
  577.             }  
  578.         }  
  579.     }  
  580.   
  581.     private void handleOutputParameterResults(StatementScope statementScope,  
  582.             ResultMap resultMap, ResultSet rs, RowHandlerCallback callback)  
  583.             throws SQLException {  
  584.         ResultMap orig = statementScope.getResultMap();  
  585.         try {  
  586.             statementScope.setResultSet(rs);  
  587.             if (resultMap != null) {  
  588.                 statementScope.setResultMap(resultMap);  
  589.   
  590.                 // Get Results  
  591.                 while (rs.next()) {  
  592.                     Object[] columnValues = resultMap.resolveSubMap(  
  593.                             statementScope, rs).getResults(statementScope, rs);  
  594.                     callback.handleResultObject(statementScope, columnValues,  
  595.                             rs);  
  596.                 }  
  597.             }  
  598.         } finally {  
  599.             statementScope.setResultSet(null);  
  600.             statementScope.setResultMap(orig);  
  601.         }  
  602.     }  
  603.   
  604.     /** 
  605.      * Clean up any batches on the session 
  606.      *  
  607.      * @param sessionScope 
  608.      *            - the session to clean up 
  609.      */  
  610.     public void cleanup(SessionScope sessionScope) {  
  611.         Batch batch = (Batch) sessionScope.getBatch();  
  612.         if (batch != null) {  
  613.             batch.cleanupBatch(sessionScope);  
  614.             sessionScope.setBatch(null);  
  615.         }  
  616.     }  
  617.   
  618.     private PreparedStatement prepareStatement(SessionScope sessionScope,  
  619.             Connection conn, String sql, Integer rsType) throws SQLException {  
  620.         SqlMapExecutorDelegate delegate = ((SqlMapClientImpl) sessionScope  
  621.                 .getSqlMapExecutor()).getDelegate();  
  622.         if (sessionScope.hasPreparedStatementFor(sql)) {  
  623.             return sessionScope.getPreparedStatement((sql));  
  624.         } else {  
  625.             PreparedStatement ps = conn.prepareStatement(sql,  
  626.                     rsType.intValue(), ResultSet.CONCUR_READ_ONLY);  
  627.             sessionScope.putPreparedStatement(delegate, sql, ps);  
  628.             return ps;  
  629.         }  
  630.     }  
  631.   
  632.     private CallableStatement prepareCall(SessionScope sessionScope,  
  633.             Connection conn, String sql, Integer rsType) throws SQLException {  
  634.         SqlMapExecutorDelegate delegate = ((SqlMapClientImpl) sessionScope  
  635.                 .getSqlMapExecutor()).getDelegate();  
  636.         if (sessionScope.hasPreparedStatementFor(sql)) {  
  637.             return (CallableStatement) sessionScope.getPreparedStatement((sql));  
  638.         } else {  
  639.             CallableStatement cs = conn.prepareCall(sql, rsType.intValue(),  
  640.                     ResultSet.CONCUR_READ_ONLY);  
  641.             sessionScope.putPreparedStatement(delegate, sql, cs);  
  642.             return cs;  
  643.         }  
  644.     }  
  645.   
  646.     private static PreparedStatement prepareStatement(  
  647.             SessionScope sessionScope, Connection conn, String sql)  
  648.             throws SQLException {  
  649.         SqlMapExecutorDelegate delegate = ((SqlMapClientImpl) sessionScope  
  650.                 .getSqlMapExecutor()).getDelegate();  
  651.         if (sessionScope.hasPreparedStatementFor(sql)) {  
  652.             return sessionScope.getPreparedStatement((sql));  
  653.         } else {  
  654.             PreparedStatement ps = conn.prepareStatement(sql);  
  655.             sessionScope.putPreparedStatement(delegate, sql, ps);  
  656.             return ps;  
  657.         }  
  658.     }  
  659.   
  660.     private CallableStatement prepareCall(SessionScope sessionScope,  
  661.             Connection conn, String sql) throws SQLException {  
  662.         SqlMapExecutorDelegate delegate = ((SqlMapClientImpl) sessionScope  
  663.                 .getSqlMapExecutor()).getDelegate();  
  664.         if (sessionScope.hasPreparedStatementFor(sql)) {  
  665.             return (CallableStatement) sessionScope.getPreparedStatement((sql));  
  666.         } else {  
  667.             CallableStatement cs = conn.prepareCall(sql);  
  668.             sessionScope.putPreparedStatement(delegate, sql, cs);  
  669.             return cs;  
  670.         }  
  671.     }  
  672.   
  673.     private static void closeStatement(SessionScope sessionScope,  
  674.             PreparedStatement ps) {  
  675.         if (ps != null) {  
  676.             if (!sessionScope.hasPreparedStatement(ps)) {  
  677.                 try {  
  678.                     ps.close();  
  679.                 } catch (SQLException e) {  
  680.                     // ignore  
  681.                 }  
  682.             }  
  683.         }  
  684.     }  
  685.   
  686.     /** 
  687.      * @param rs 
  688.      */  
  689.     private static void closeResultSet(ResultSet rs) {  
  690.         if (rs != null) {  
  691.             try {  
  692.                 rs.close();  
  693.             } catch (SQLException e) {  
  694.                 // ignore  
  695.             }  
  696.         }  
  697.     }  
  698.   
  699.     private static void setStatementTimeout(MappedStatement mappedStatement,  
  700.             Statement statement) throws SQLException {  
  701.         if (mappedStatement.getTimeout() != null) {  
  702.             statement.setQueryTimeout(mappedStatement.getTimeout().intValue());  
  703.         }  
  704.     }  
  705.   
  706.     //  
  707.     // Inner Classes  
  708.     //  
  709.   
  710.     private static class Batch {  
  711.         private String currentSql;  
  712.         private List statementList = new ArrayList();  
  713.         private List batchResultList = new ArrayList();  
  714.         private int size;  
  715.   
  716.         /** 
  717.          * Create a new batch 
  718.          */  
  719.         public Batch() {  
  720.             this.size = 0;  
  721.         }  
  722.   
  723.         /** 
  724.          * Getter for the batch size 
  725.          *  
  726.          * @return - the batch size 
  727.          */  
  728.         public int getSize() {  
  729.             return size;  
  730.         }  
  731.   
  732.         /** 
  733.          * Add a prepared statement to the batch 
  734.          *  
  735.          * @param statementScope 
  736.          *            - the request scope 
  737.          * @param conn 
  738.          *            - the database connection 
  739.          * @param sql 
  740.          *            - the SQL to add 
  741.          * @param parameters 
  742.          *            - the parameters for the SQL 
  743.          * @throws SQLException 
  744.          *             - if the prepare for the SQL fails 
  745.          */  
  746.         public void addBatch(StatementScope statementScope, Connection conn,  
  747.                 String sql, Object[] parameters) throws SQLException {  
  748.             PreparedStatement ps = null;  
  749.             if (currentSql != null && currentSql.equals(sql)) {  
  750.                 int last = statementList.size() - 1;  
  751.                 ps = (PreparedStatement) statementList.get(last);  
  752.             } else {  
  753.                 ps = prepareStatement(statementScope.getSession(), conn, sql);  
  754.                 setStatementTimeout(statementScope.getStatement(), ps);  
  755.                 currentSql = sql;  
  756.                 statementList.add(ps);  
  757.                 batchResultList.add(new BatchResult(statementScope  
  758.                         .getStatement().getId(), sql));  
  759.             }  
  760.             statementScope.getParameterMap().setParameters(statementScope, ps,  
  761.                     parameters);  
  762.             ps.addBatch();  
  763.             size++;  
  764.         }  
  765.   
  766.         /** 
  767.          * TODO (Jeff Butler) - maybe this method should be deprecated in some 
  768.          * release, and then removed in some even later release. 
  769.          * executeBatchDetailed gives much more complete information. <p/> 
  770.          * Execute the current session's batch 
  771.          *  
  772.          * @return - the number of rows updated 
  773.          * @throws SQLException 
  774.          *             - if the batch fails 
  775.          */  
  776.         public int executeBatch() throws SQLException {  
  777.             int totalRowCount = 0;  
  778.             for (int i = 0, n = statementList.size(); i < n; i++) {  
  779.                 PreparedStatement ps = (PreparedStatement) statementList.get(i);  
  780.                 int[] rowCounts = ps.executeBatch();  
  781.                 for (int j = 0; j < rowCounts.length; j++) {  
  782.                     if (rowCounts[j] == Statement.SUCCESS_NO_INFO) {  
  783.                         // do nothing  
  784.                     } else if (rowCounts[j] == Statement.EXECUTE_FAILED) {  
  785.                         throw new SQLException(  
  786.                                 "The batched statement at index " + j  
  787.                                         + " failed to execute.");  
  788.                     } else {  
  789.                         totalRowCount += rowCounts[j];  
  790.                     }  
  791.                 }  
  792.             }  
  793.             return totalRowCount;  
  794.         }  
  795.   
  796.         /** 
  797.          * Batch execution method that returns all the information the driver 
  798.          * has to offer. 
  799.          *  
  800.          * @return a List of BatchResult objects 
  801.          * @throws BatchException 
  802.          *             (an SQLException sub class) if any nested batch fails 
  803.          * @throws SQLException 
  804.          *             if a database access error occurs, or the drive does not 
  805.          *             support batch statements 
  806.          * @throws BatchException 
  807.          *             if the driver throws BatchUpdateException 
  808.          */  
  809.         public List executeBatchDetailed() throws SQLException, BatchException {  
  810.             List answer = new ArrayList();  
  811.             for (int i = 0, n = statementList.size(); i < n; i++) {  
  812.                 BatchResult br = (BatchResult) batchResultList.get(i);  
  813.                 PreparedStatement ps = (PreparedStatement) statementList.get(i);  
  814.                 try {  
  815.                     br.setUpdateCounts(ps.executeBatch());  
  816.                 } catch (BatchUpdateException e) {  
  817.                     StringBuffer message = new StringBuffer();  
  818.                     message.append("Sub batch number ");  
  819.                     message.append(i + 1);  
  820.                     message.append(" failed.");  
  821.                     if (i > 0) {  
  822.                         message.append(" ");  
  823.                         message.append(i);  
  824.                         message  
  825.                                 .append(" prior sub batch(s) completed successfully, but will be rolled back.");  
  826.                     }  
  827.                     throw new BatchException(message.toString(), e, answer, br  
  828.                             .getStatementId(), br.getSql());  
  829.                 }  
  830.                 answer.add(br);  
  831.             }  
  832.             return answer;  
  833.         }  
  834.   
  835.         /** 
  836.          * Close all the statements in the batch and clear all the statements 
  837.          *  
  838.          * @param sessionScope 
  839.          */  
  840.         public void cleanupBatch(SessionScope sessionScope) {  
  841.             for (int i = 0, n = statementList.size(); i < n; i++) {  
  842.                 PreparedStatement ps = (PreparedStatement) statementList.get(i);  
  843.                 closeStatement(sessionScope, ps);  
  844.             }  
  845.             currentSql = null;  
  846.             statementList.clear();  
  847.             batchResultList.clear();  
  848.             size = 0;  
  849.         }  
  850.     }  
  851.   
  852.     private void setupResultObjectFactory(StatementScope statementScope) {  
  853.         SqlMapClientImpl client = (SqlMapClientImpl) statementScope  
  854.                 .getSession().getSqlMapClient();  
  855.         ResultObjectFactoryUtil.setResultObjectFactory(client  
  856.                 .getResultObjectFactory());  
  857.         ResultObjectFactoryUtil.setStatementId(statementScope.getStatement()  
  858.                 .getId());  
  859.     }  
  860. }  

Dialect.java 
Java代码   收藏代码
  1. package com.ibatis.sqlmap.engine.execution;  
  2.   
  3. public class Dialect {  
  4.     private static final String SQL_END_DELIMITER = ";";  
  5.   
  6.     public static String getLimitString(String dbName, String sql, int offset,  
  7.             int limit) {  
  8.         String limitString = sql;  
  9.         if (dbName.toLowerCase().indexOf("mysql") != -1) {  
  10.             limitString = getMysqlLimitString(sql, offset, limit);  
  11.         }  
  12.         if (dbName.toLowerCase().indexOf("microsoft sql server") != -1) {  
  13.             limitString = getMssqlLimitString(sql, offset, limit);  
  14.         }  
  15.         if (dbName.toLowerCase().indexOf("oracle") != -1) {  
  16.             limitString = getOracleLimitString(sql, offset, limit);  
  17.         }  
  18.         if (dbName.toLowerCase().indexOf("db2") != -1) {  
  19.             limitString = getDB2LimitString(sql, offset, limit);  
  20.         }  
  21.           
  22.         return limitString;  
  23.     }  
  24.   
  25.     private static String getMysqlLimitString(String sql, int offset, int limit) {  
  26.         sql = trim(sql);  
  27.         StringBuffer sb = new StringBuffer(sql.length() + 20);  
  28.         sb.append(sql);  
  29.         if (offset > 0) {  
  30.             sb.append(" limit ").append(offset).append(',').append(limit);  
  31.         } else {  
  32.             sb.append(" limit ").append(limit);  
  33.         }  
  34.         return sb.toString();  
  35.     }  
  36.   
  37.     private static String getOracleLimitString(String sql, int offset, int limit) {  
  38.         sql = trim(sql);  
  39.         StringBuffer sb = new StringBuffer(sql.length() + 100);  
  40.         if (offset > 0) {  
  41.             sb.append("select * from ( select row_.*, rownum rownum_ from ( ")  
  42.                     .append(sql).append(" ) row_ where rownum <= ").append(  
  43.                             offset + limit).append(") where rownum_ > ")  
  44.                     .append(offset);  
  45.         } else {  
  46.             sb.append("select * from ( ").append(sql).append(  
  47.                     " ) where rownum <= ").append(limit);  
  48.         }  
  49.         return sb.toString();  
  50.     }  
  51.   
  52.     private static String getMssqlLimitString(String sql, int offset, int limit) {  
  53.         return null;  
  54.     }  
  55.       
  56.     private static String getDB2LimitString(String sql, int offset, int limit) {          
  57.         return null;  
  58.     }  
  59.   
  60.     private static String trim(String sql) {  
  61.         sql = sql.trim();  
  62.         if (sql.endsWith(SQL_END_DELIMITER)) {  
  63.             sql = sql.substring(0, sql.length() - 1  
  64.                     - SQL_END_DELIMITER.length());  
  65.         }  
  66.         return sql;  
  67.     }  
  68. }  

你可能感兴趣的:(iBatis分页)