mybatis的攔截器實現統計分析sql的執行時間,mybatis統計分析

來源:互聯網
上載者:User

mybatis的攔截器實現統計分析sql的執行時間,mybatis統計分析

轉載自:http://blog.csdn.net/andyzhaojianhui/article/details/72823055

對於mybatis的攔截器這個想法我來自於三個地方

也就是下面這個三個地方是可以使用的,其他的情況需要開發人員根據實際情況來使用。

1、對於分頁的查詢,我們可以對於分頁的方法採用比較規範的命名,然後根據這個命名來攔截需要分頁查詢的sql然後把分頁的總數,分頁數,頁碼數,頁碼總數等放在一個對象中返回去,這樣分頁只要調用dao的一個方法即可。

2、讀寫分離,我們可以在sql執行之前,擷取sql是不是查詢方法,然後根據這個條件去控制需要訪問的資料來源。

3、需要統計分析sql的執行時間(這邊要說的是這裡的執行包含了網路頻寬,因為不是在mysql執行前後做的攔截,所以這裡的sql並不只是sql在資料庫真正執行的時間,要比實際長)

 

如何?這樣一個攔截器

首先mybatis官方早就想到我們開發會有這樣的需求,所以開放了一個org.apache.ibatis.plugin.Interceptor這樣一個介面。

我們只要實現這個介面並且加上註解然後重寫intercept方法。

最後如果你使用的是mybatis.xml也就是mybatis本身單獨的配置,你可以需要在這裡配置相應的攔截器名字等。

如果你使用的是spring管理的mybatis,那麼你需要在spring設定檔裡面配置註冊相應的攔截器。

 

代碼實現

下面對於3,也就是實現統計sql執行時間,簡單摘錄一下實現代碼。

還有兩種開發可以根據自己的想法去實現和摸索。

- Hide code
package com.ssm;import java.text.DateFormat;import java.util.Date;import java.util.List;import java.util.Locale;import java.util.Properties;import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.ParameterMapping;import org.apache.ibatis.plugin.Interceptor;import org.apache.ibatis.plugin.Intercepts;import org.apache.ibatis.plugin.Invocation;import org.apache.ibatis.plugin.Plugin;import org.apache.ibatis.plugin.Signature;import org.apache.ibatis.reflection.MetaObject;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import org.apache.ibatis.type.TypeHandlerRegistry;import org.apache.log4j.Logger;  @Intercepts({      @Signature(type = Executor.class, method = "update", args = { MappedStatement.class, Object.class }),      @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,              RowBounds.class, ResultHandler.class }) })  public class SqlStatementInterceptor implements Interceptor{            private static Logger logger = Logger.getLogger(SqlStatementInterceptor.class);        @SuppressWarnings("unused")      private Properties properties;            @Override      public Object intercept(Invocation arg0) throws Throwable {          MappedStatement mappedStatement = (MappedStatement) arg0.getArgs()[0];          Object parameter = null;          if (arg0.getArgs().length > 1) {              parameter = arg0.getArgs()[1];          }          String sqlId = mappedStatement.getId();          BoundSql boundSql = mappedStatement.getBoundSql(parameter);          Configuration configuration = mappedStatement.getConfiguration();                    Object returnValue = null;          long start = System.currentTimeMillis();          returnValue = arg0.proceed();          long end = System.currentTimeMillis();          long time = (end - start);            if (time > 1) {              String sql = getSql(configuration, boundSql, sqlId, time);              logger.error(sql);        }                    return returnValue;      }            public static String getSql(Configuration configuration, BoundSql boundSql, String sqlId, long time) {          String sql = showSql(configuration, boundSql);          StringBuilder str = new StringBuilder(100);          str.append(sqlId);          str.append(":");          str.append(sql);          str.append(":");          str.append(time);          str.append("ms");          return str.toString();      }            public static String showSql(Configuration configuration, BoundSql boundSql) {          Object parameterObject = boundSql.getParameterObject();          List<ParameterMapping> parameterMappings = boundSql.getParameterMappings();          String sql = boundSql.getSql().replaceAll("[\\s]+", " ");          if (parameterMappings.size() > 0 && parameterObject != null) {              TypeHandlerRegistry typeHandlerRegistry = configuration.getTypeHandlerRegistry();              if (typeHandlerRegistry.hasTypeHandler(parameterObject.getClass())) {                  sql = sql.replaceFirst("\\?", getParameterValue(parameterObject));                 } else {                  MetaObject metaObject = configuration.newMetaObject(parameterObject);                  for (ParameterMapping parameterMapping : parameterMappings) {                      String propertyName = parameterMapping.getProperty();                      if (metaObject.hasGetter(propertyName)) {                          Object obj = metaObject.getValue(propertyName);                          sql = sql.replaceFirst("\\?", getParameterValue(obj));                      } else if (boundSql.hasAdditionalParameter(propertyName)) {                          Object obj = boundSql.getAdditionalParameter(propertyName);                          sql = sql.replaceFirst("\\?", getParameterValue(obj));                      }                  }              }          }          return sql;      }            private static String getParameterValue(Object obj) {          String value = null;          if (obj instanceof String) {              value = "'" + obj.toString() + "'";          } else if (obj instanceof Date) {              DateFormat formatter = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.DEFAULT, Locale.CHINA);              value = "'" + formatter.format(new Date()) + "'";          } else {              if (obj != null) {                  value = obj.toString();              } else {                  value = "";              }             }          return value;      }        @Override      public Object plugin(Object arg0) {          return Plugin.wrap(arg0, this);      }        @Override      public void setProperties(Properties arg0) {          this.properties = arg0;      }    }

下面是spring中的配置,如果你是單獨配置mybatis設定檔的話,你需要查詢一下如何配置

- Hide code
<!-- 配置mybitasSqlSessionFactoryBean -->    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">        <property name="dataSource" ref="dataSource" />        <property name="typeAliasesPackage" value="com/ssm/entity"></property>        <property name="mapperLocations" value="classpath*:com/ssm/dao/sqlxml/*.xml"></property>                                <property name="plugins">            <array>                <bean class="com.ssm.SqlStatementInterceptor">                    <property name="properties">                        <value>                            property-key=property-value                        </value>                    </property>                </bean>            </array>        </property>    </bean>

會在log日誌中輸出最後執行的sql和sqlID和sql執行的時間。

 

 

參考資料:

分頁實現(本人沒有親自實現,因為現實情況還沒有這樣特別需要這樣的商務邏輯):

http://www.cnblogs.com/jethypc/p/5149183.html

執行時間統計實現(我修改了其中spring的配置,不知為何下面博主的配置並沒有用):

http://blog.csdn.net/tq02h2a/article/details/50772652

讀寫分離實現(其中的第四種方案就是利用了攔截器):

http://www.jianshu.com/p/2222257f96d3


查看評論

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.