The interceptor of mybatis implements statistical analysis of SQL Execution time, And mybatis performs statistical analysis.

Source: Internet
Author: User

The interceptor of mybatis implements statistical analysis of SQL Execution time, And mybatis performs statistical analysis.

Reprinted from: http://blog.csdn.net/andyzhaojianhui/article/details/72823055


The idea of the interceptor for mybatis comes from three places


That is, the following three areas can be used. In other cases, developers need to use them according to the actual situation.

1. for paging queries, we can adopt a standardized naming method for paging queries. Then, we can intercept the SQL statements that require paging queries based on the naming method and divide the total number of pages into several pages, the number of pages and the total number of pages are returned in an object. In this way, you only need to call the dao method on the page.

2. read/write Splitting: Before executing the SQL statement, obtain whether the SQL statement is a query method and control the data source to be accessed based on this condition.

3. Statistical analysis of the SQL Execution time is required (the execution here includes network bandwidth because it is not intercepted before and after mysql execution, so the SQL here is not only the real execution time of SQL in the database, it is longer than the actual time)

 

How to implement such an interceptor

First, mybatis has long been expected to have such a requirement for our development, so an org. apache. ibatis. plugin. Interceptor interface is opened.

We only need to implement this interface and add annotations and then rewrite the intercept method.

If you use mybatis. xml, that is, the configuration of mybatis, you can configure the corresponding interceptor name here.

If you are using mybatis managed by spring, you need to configure and register the corresponding interceptor in the spring configuration file.

 

Code Implementation

The following is a brief excerpt of the implementation code for "3", that is, to calculate the SQL Execution time.

There are two other types of development that can be implemented and explored based on your own ideas.

-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;      }    }

 

The following is the configuration in spring. If you configure the mybatis configuration file separately, you need to query how to configure

-Hide code
<! -- Configure 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>

The last executed SQL and sqlID and SQL Execution time are output in the log.

 

 

References:

Implement by PAGE (I did not implement it myself, because the actual situation does not have such a special need for such business logic ):

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

Execute the time statistics (I modified the spring configuration, but I don't know why the following configuration is useless ):

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

Read/write splitting (the fourth solution is to use the interceptor ):

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


View comments


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

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.