/**
   *
   *
   * <pre>
   * 查询总数
   * </pre>
   *
   * @author jundong.xu_C
   * @param page
   * @param parameterObject
   * @param mappedStatement
   * @param connection
   * @throws SQLException
   */
  protected void queryTotalRecord(
      Page<?> page, Object parameterObject, MappedStatement mappedStatement, Connection connection)
      throws SQLException {
    BoundSql boundSql = mappedStatement.getBoundSql(parameterObject);
    String sql = boundSql.getSql();
    String countSql = this.buildCountSql(sql);
    if (log.isDebugEnabled()) {
      log.debug("分页时, 生成countSql: " + countSql);
    }

    List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
    BoundSql countBoundSql =
        new BoundSql(
            mappedStatement.getConfiguration(), countSql, parameterMappings, parameterObject);
    ParameterHandler parameterHandler =
        new DefaultParameterHandler(mappedStatement, parameterObject, countBoundSql);
    PreparedStatement pstmt = null;
    ResultSet rs = null;
    try {
      pstmt = connection.prepareStatement(countSql);
      parameterHandler.setParameters(pstmt);
      rs = pstmt.executeQuery();
      if (rs.next()) {
        long totalRecord = rs.getLong(1);
        int pageSize = page.getPageSize();
        int totalPage = (int) (totalRecord + pageSize - 1) / pageSize;
        page.setTotalSize(totalRecord);
        page.setTotalPage(totalPage);
      }
    } finally {
      if (rs != null)
        try {
          rs.close();
        } catch (Exception e) {
          if (log.isWarnEnabled()) {
            log.warn("关闭ResultSet时异常.", e);
          }
        }
      if (pstmt != null)
        try {
          pstmt.close();
        } catch (Exception e) {
          if (log.isWarnEnabled()) {
            log.warn("关闭PreparedStatement时异常.", e);
          }
        }
    }
  }
  /**
   * 对SQL参数(?)设值
   *
   * @param ps
   * @param mappedStatement
   * @param boundSql
   * @param parameterObject
   * @throws SQLException
   */
  private void setParameters(
      PreparedStatement ps, MappedStatement mappedStatement, BoundSql boundSql)
      throws SQLException {

    ParameterHandler parameterHandler =
        mappedStatement
            .getConfiguration()
            .newParameterHandler(mappedStatement, boundSql.getParameterObject(), boundSql);
    parameterHandler.setParameters(ps);
  }
  /**
   * 获取总记录数
   *
   * @param sql 原始sql语句
   * @param conn
   * @param ms
   * @param boundSql
   * @return
   * @throws SQLException
   */
  private int getTotalCount(String sql, Connection conn, MappedStatement ms, BoundSql boundSql)
      throws SQLException {
    int start = sql.indexOf("from");
    if (start == -1) {
      throw new RuntimeException("statement has no 'from' keyword");
    }
    int stop = sql.indexOf("order by");
    if (stop == -1) {
      stop = sql.length();
    }

    String countSql = "select count(0) " + sql.substring(start, stop);
    BoundSql countBoundSql =
        new BoundSql(
            ms.getConfiguration(),
            countSql,
            boundSql.getParameterMappings(),
            boundSql.getParameterObject());
    ParameterHandler parameterHandler =
        new DefaultParameterHandler(ms, boundSql.getParameterObject(), countBoundSql);
    PreparedStatement stmt = null;
    ResultSet rs = null;
    int count = 0;
    try {
      stmt = conn.prepareStatement(countSql);
      // 通过parameterHandler给PreparedStatement对象设置参数
      parameterHandler.setParameters(stmt);
      rs = stmt.executeQuery();
      if (rs.next()) {
        count = rs.getInt(1);
      }
    } finally {
      CloseableUtil.closeQuietly(rs);
      CloseableUtil.closeQuietly(stmt);
    }
    return count;
  }
 public void handleOutputParameters(CallableStatement cs) throws SQLException {
   final Object parameterObject = parameterHandler.getParameterObject();
   final MetaObject metaParam = configuration.newMetaObject(parameterObject);
   final List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();
   for (int i = 0; i < parameterMappings.size(); i++) {
     final ParameterMapping parameterMapping = parameterMappings.get(i);
     if (parameterMapping.getMode() == ParameterMode.OUT
         || parameterMapping.getMode() == ParameterMode.INOUT) {
       if (ResultSet.class.equals(parameterMapping.getJavaType())) {
         handleRefCursorOutputParameter(
             (ResultSet) cs.getObject(i + 1), parameterMapping, metaParam);
       } else {
         final TypeHandler<?> typeHandler = parameterMapping.getTypeHandler();
         metaParam.setValue(parameterMapping.getProperty(), typeHandler.getResult(cs, i + 1));
       }
     }
   }
 }
 /**
  * 获取总计录
  *
  * @param parameterHandler
  * @param connection
  * @param countSql
  * @return
  * @throws Exception
  */
 private int getTotal(ParameterHandler parameterHandler, Connection connection, String countSql)
     throws Exception {
   // MetaObject metaStatementHandler =
   // MetaObject.forObject(parameterHandler);
   // Object parameterObject =
   // metaStatementHandler.getValue("parameterObject");
   // TODO 缓存具有相同SQL语句和参数的总数
   PreparedStatement prepareStatement = connection.prepareStatement(countSql);
   parameterHandler.setParameters(prepareStatement);
   ResultSet rs = prepareStatement.executeQuery();
   int count = 0;
   if (rs.next()) {
     count = rs.getInt(1);
   }
   rs.close();
   prepareStatement.close();
   return count;
 }