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 禮物 閱讀(4802) 評論(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中包含子查詢就不好用了  回復  更多評論
            

          主站蜘蛛池模板: 道孚县| 临泉县| 孟连| 会理县| 大余县| 远安县| 江北区| 永寿县| 定州市| 新津县| 辰溪县| 长岛县| 阳朔县| 尼玛县| 淮安市| 磐安县| 鄂伦春自治旗| 大同市| 彰武县| 龙游县| 新平| 江津市| 庆云县| 大田县| 富平县| 梁山县| 平果县| 获嘉县| 阿坝| 靖西县| 刚察县| 天峨县| 昂仁县| 右玉县| 陆良县| 客服| 东山县| 商城县| 柳江县| 灵山县| 泌阳县|