Terry.Li-彬

          虛其心,可解天下之問;專其心,可治天下之學;靜其心,可悟天下之理;恒其心,可成天下之業。

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
            143 隨筆 :: 344 文章 :: 130 評論 :: 0 Trackbacks
          下面的內容是基于ibatis2.2,以后的版本是否提供了類似功能不太清楚,甚至這個版本是否提供也沒有細究(好像沒有)。

          很多時候我們需要執行select語句對應的count語句,例如分頁查詢時要得到結果的記錄數,但在ibatis的映射文件中我們只想寫一條select語句,而count語句直接由這條語句生成,這可以省去很多不必要的語句關聯,下面的代碼可以實現這一點。

          CountStatementUtil.java

          java 代碼
          package com.aladdin.dao.ibatis.ext;

          import java.sql.Connection;
          import java.sql.SQLException;
          import java.util.List;

          import com.aladdin.util.ReflectUtil;
          import com.ibatis.common.jdbc.exception.NestedSQLException;
          import com.ibatis.sqlmap.client.event.RowHandler;
          import com.ibatis.sqlmap.engine.impl.ExtendedSqlMapClient;
          import com.ibatis.sqlmap.engine.mapping.parameter.ParameterMap;
          import com.ibatis.sqlmap.engine.mapping.result.AutoResultMap;
          import com.ibatis.sqlmap.engine.mapping.result.BasicResultMap;
          import com.ibatis.sqlmap.engine.mapping.result.ResultMap;
          import com.ibatis.sqlmap.engine.mapping.sql.Sql;
          import com.ibatis.sqlmap.engine.mapping.statement.ExecuteListener;
          import com.ibatis.sqlmap.engine.mapping.statement.MappedStatement;
          import com.ibatis.sqlmap.engine.mapping.statement.RowHandlerCallback;
          import com.ibatis.sqlmap.engine.mapping.statement.SelectStatement;
          import com.ibatis.sqlmap.engine.scope.ErrorContext;
          import com.ibatis.sqlmap.engine.scope.RequestScope;

          public class CountStatementUtil {

          public static MappedStatement createCountStatement(MappedStatement selectStatement) {
          return new CountStatement((SelectStatement) selectStatement);
          }

          public static String getCountStatementId(String selectStatementId) {
          return "__" + selectStatementId + "Count__";
          }

          }

          class CountStatement extends SelectStatement {

          public CountStatement(SelectStatement selectStatement) {
          super();
          setId(CountStatementUtil.getCountStatementId(selectStatement
          .getId()));
          setResultSetType(selectStatement.getResultSetType());
          setFetchSize(1);
          setParameterMap(selectStatement.getParameterMap());
          setParameterClass(selectStatement.getParameterClass());
          setSql(selectStatement.getSql());
          setResource(selectStatement.getResource());
          setSqlMapClient(selectStatement.getSqlMapClient());
          setTimeout(selectStatement.getTimeout());
          List executeListeners = (List) ReflectUtil.getFieldValue(
          selectStatement, "executeListeners", List.class);
          if (executeListeners != null) {
          for (Object listener : executeListeners) {
          addExecuteListener((ExecuteListener) listener);
          }
          }
          BasicResultMap resultMap = new AutoResultMap(
          ((ExtendedSqlMapClient) getSqlMapClient()).getDelegate(), false);
          resultMap.setId(getId() + "-AutoResultMap");
          resultMap.setResultClass(Long.class);
          resultMap.setResource(getResource());
          setResultMap(resultMap);

          }

          protected void executeQueryWithCallback(RequestScope request,
          Connection conn, Object parameterObject, Object resultObject,
          RowHandler rowHandler, int skipResults, int maxResults)
          throws SQLException {
          ErrorContext errorContext = request.getErrorContext();
          errorContext
          .setActivity("preparing the mapped statement for execution");
          errorContext.setObjectId(this.getId());
          errorContext.setResource(this.getResource());

          try {
          parameterObject = validateParameter(parameterObject);

          Sql sql = getSql();

          errorContext.setMoreInfo("Check the parameter map.");
          ParameterMap parameterMap = sql.getParameterMap(request,
          parameterObject);

          errorContext.setMoreInfo("Check the result map.");
          ResultMap resultMap = getResultMap(request, parameterObject, sql);

          request.setResultMap(resultMap);
          request.setParameterMap(parameterMap);

          errorContext.setMoreInfo("Check the parameter map.");
          Object[] parameters = parameterMap.getParameterObjectValues(
          request, parameterObject);

          errorContext.setMoreInfo("Check the SQL statement.");
          String sqlString = getSqlString(request, parameterObject, sql);

          errorContext.setActivity("executing mapped statement");
          errorContext
          .setMoreInfo("Check the SQL statement or the result map.");
          RowHandlerCallback callback = new RowHandlerCallback(resultMap,
          resultObject, rowHandler);
          sqlExecuteQuery(request, conn, sqlString, parameters, skipResults,
          maxResults, callback);

          errorContext.setMoreInfo("Check the output parameters.");
          if (parameterObject != null) {
          postProcessParameterObject(request, parameterObject, parameters);
          }

          errorContext.reset();
          sql.cleanup(request);
          notifyListeners();
          } catch (SQLException e) {
          errorContext.setCause(e);
          throw new NestedSQLException(errorContext.toString(), e
          .getSQLState(), e.getErrorCode(), e);
          } catch (Exception e) {
          errorContext.setCause(e);
          throw new NestedSQLException(errorContext.toString(), e);
          }
          }

          private String getSqlString(RequestScope request, Object parameterObject,
          Sql sql) {
          String sqlString = sql.getSql(request, parameterObject);
          int start = sqlString.toLowerCase().indexOf("from");
          if (start >= 0) {
          sqlString = "SELECT COUNT(*) AS c " + sqlString.substring(start);
          }
          return sqlString;
          }

          private ResultMap getResultMap(RequestScope request,
          Object parameterObject, Sql sql) {
          return getResultMap();
          }

          }

          上面代碼中的getSqlString方法可以根據自己系統select語句的復雜程度完善,這里給出的是最簡單的實現。

          使用上面的類即可由select語句生成count語句,下面是通過spring使用的代碼:

          BaseDaoiBatis.java

          java 代碼
          //...
          public abstract class BaseDaoiBatis extends SqlMapClientDaoSupport {

          //...

          protected long getObjectTotal(String selectQuery, Object parameterObject) {
          prepareCountQuery(selectQuery);
          //...
          return (Long) getSqlMapClientTemplate().queryForObject(
          CountStatementUtil.getCountStatementId(selectQuery),
          parameterObject);
          }

          protected void prepareCountQuery(String selectQuery) {

          String countQuery = CountStatementUtil.getCountStatementId(selectQuery);
          if (logger.isDebugEnabled()) {
          logger.debug("Convert " + selectQuery + " to " + countQuery);
          }
          SqlMapClient sqlMapClient = getSqlMapClientTemplate().getSqlMapClient();
          if (sqlMapClient instanceof ExtendedSqlMapClient) {
          SqlMapExecutorDelegate delegate = ((ExtendedSqlMapClient) sqlMapClient)
          .getDelegate();
          try {
          delegate.getMappedStatement(countQuery);
          } catch (SqlMapException e) {
          delegate.addMappedStatement(CountStatementUtil
          .createCountStatement(delegate
          .getMappedStatement(selectQuery)));
          }

          }
          }

          //...
          }
          posted on 2008-05-03 00:31 禮物 閱讀(4803) 評論(3)  編輯  收藏 所屬分類: ibatis + spring

          評論

          # re: ibatis中由SELECT語句自動生成COUNT語句 2011-01-13 12:18 tylerLimin
          Hi Terry.
          按你上面寫的那樣可以實現分頁條件中的 resultCount(記錄數)統計嗎?它們是共用一條查詢語句?我試了試不行哦。不知你那里有沒有好的建議沒,有,請回復。多謝!  回復  更多評論
            

          # re: ibatis中由SELECT語句自動生成COUNT語句 2011-01-17 13:44 禮物
          可以實現count查詢,原則上會生成兩條sql語句,一條是count一條是具體分頁的,這個代碼已經寫了很早了,你最好進行debug跟蹤一下就可以知道了  回復  更多評論
            

          # re: ibatis中由SELECT語句自動生成COUNT語句 2011-04-25 19:29 joliny
          有沒有通用的呀??!如果sql中包含子查詢就不好用了  回復  更多評論
            

          主站蜘蛛池模板: 枝江市| 南川市| 文成县| 承德县| 宁津县| 扬州市| 托里县| 中方县| 天长市| 沙坪坝区| 沾益县| 富民县| 成安县| 武汉市| 宜宾市| 达日县| 无极县| 德州市| 莆田市| 桃源县| 连江县| 岳池县| 华安县| 洪泽县| 库伦旗| 康马县| 松阳县| 巴里| 旅游| 正安县| 樟树市| 吴桥县| 海丰县| 磴口县| 盐边县| 科技| 柳州市| 寻甸| 牙克石市| 武鸣县| 屯昌县|