zoukankan      html  css  js  c++  java
  • MyBatis打印SQL执行时间

    1、plugins

    MyBatis官网对于plugins的描述是这样的:

    MyBatis allows you to intercept calls to at certain points within the execution of a mapped statement. By default, MyBatis allows plug-ins to intercept method calls of:

    • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    • ParameterHandler (getParameterObject, setParameters)
    • ResultSetHandler (handleResultSets, handleOutputParameters)
    • StatementHandler (prepare, parameterize, batch, update, query)

    The details of these classes methods can be discovered by looking at the full method signature of each, and the source code which is available with each MyBatis release. You should understand the behaviour of the method you’re overriding, assuming you’re doing something more than just monitoring calls. If you attempt to modify or override the behaviour of a given method, you’re likely to break the core of MyBatis. These are low level classes and methods, so use plug-ins with caution.

    Using plug-ins is pretty simple given the power they provide. Simply implement the Interceptor interface, being sure to specify the signatures you want to intercept.

    // ExamplePlugin.java
    @Intercepts({@Signature(
      type= Executor.class,
      method = "update",
      args = {MappedStatement.class,Object.class})})
    public class ExamplePlugin implements Interceptor {
      public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed();
      }
      public Object plugin(Object target) {
        return Plugin.wrap(target, this);
      }
      public void setProperties(Properties properties) {
      }
    }
    <!-- mybatis-config.xml -->
    <plugins>
      <plugin interceptor="org.mybatis.example.ExamplePlugin">
        <property name="someProperty" value="100"/>
      </plugin>
    </plugins>

    The plug-in above will intercept all calls to the "update" method on the Executor instance, which is an internal object responsible for the low level execution of mapped statements.

    NOTE Overriding the Configuration Class

    In addition to modifying core MyBatis behaviour with plugins, you can also override the Configuration class entirely. Simply extend it and override any methods inside, and pass it into the call to the SqlSessionFactoryBuilder.build(myConfig) method. Again though, this could have a severe impact on the behaviour of MyBatis, so use caution.

    2、定义一个Interceptor

     1 package com.cjs.boot.interceptor;
     2 
     3 import lombok.extern.slf4j.Slf4j;
     4 import org.apache.ibatis.executor.statement.StatementHandler;
     5 import org.apache.ibatis.mapping.BoundSql;
     6 import org.apache.ibatis.plugin.*;
     7 import org.apache.ibatis.session.ResultHandler;
     8 
     9 import java.sql.Statement;
    10 import java.util.Properties;
    11 
    12 @Slf4j
    13 @Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class})})
    14 public class SqlStatementInterceptor implements Interceptor {
    15     @Override
    16     public Object intercept(Invocation invocation) throws Throwable {
    17         long startTime = System.currentTimeMillis();
    18         try {
    19             return invocation.proceed();
    20         } finally {
    21             long endTime = System.currentTimeMillis();
    22 
    23             StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
    24             BoundSql boundSql = statementHandler.getBoundSql();
    25             String sql = boundSql.getSql();
    26             sql = sql.replace("
    ", "").replace("	", "").replaceAll("\s+", " ");
    27 
    28             log.info("执行SQL: [{}]花费{}ms", sql, (endTime - startTime));
    29 
    30         }
    31     }
    32 
    33     @Override
    34     public Object plugin(Object target) {
    35         return Plugin.wrap(target, this);
    36     }
    37 
    38     @Override
    39     public void setProperties(Properties properties) {
    40 
    41     }
    42 }

    2、配置SqlSessionFactory

     1 package com.cjs.boot.config;
     2 
     3 import com.cjs.boot.interceptor.SqlStatementInterceptor;
     4 import org.apache.ibatis.plugin.Interceptor;
     5 import org.apache.ibatis.session.SqlSessionFactory;
     6 import org.mybatis.spring.SqlSessionFactoryBean;
     7 import org.springframework.context.annotation.Bean;
     8 import org.springframework.context.annotation.Configuration;
     9 import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
    10 
    11 import javax.annotation.Resource;
    12 import javax.sql.DataSource;
    13 
    14 @Configuration
    15 public class MyBatisConfig {
    16 
    17     @Resource
    18     private DataSource dataSource;
    19 
    20     @Bean
    21     public SqlSessionFactory sqlSessionFactory() throws Exception {
    22         SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
    23         sqlSessionFactoryBean.setDataSource(dataSource);
    24         sqlSessionFactoryBean.setPlugins(new Interceptor[]{new SqlStatementInterceptor()});
    25         PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
    26         sqlSessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources("classpath:mapper/*Mapper.xml"));
    27         sqlSessionFactoryBean.setTypeAliasesPackage("com.cjs.boot.domain.entity");
    28         return sqlSessionFactoryBean.getObject();
    29     }
    30 
    31 }

    3、运行效果

    2018-05-09 13:53:55.589 DEBUG 10988 --- [nio-8080-exec-2] c.c.b.m.C.selectByMerchantId             : ==>  Preparing: SELECT id, merchant_id, coupon_name, coupon_type, par_value, quantity, release_start_time, release_end_time, limit_type, limit_num, remark, create_time, update_time, yn FROM coupon_info WHERE merchant_id = ? 
    2018-05-09 13:53:55.605 DEBUG 10988 --- [nio-8080-exec-2] c.c.b.m.C.selectByMerchantId             : ==> Parameters: 10009(Integer)
    2018-05-09 13:53:55.619 DEBUG 10988 --- [nio-8080-exec-2] c.c.b.m.C.selectByMerchantId             : <==      Total: 0
    2018-05-09 13:53:55.620  INFO 10988 --- [nio-8080-exec-2] c.c.b.i.SqlStatementInterceptor          : 执行SQL: [SELECT id, merchant_id, coupon_name, coupon_type, par_value, quantity, release_start_time, release_end_time, limit_type, limit_num, remark, create_time, update_time, yn FROM coupon_info WHERE merchant_id = ?]花费15ms

    4、补充

    4.1、@Signature注解的那几个参数该怎么写

    前面文档中说了,可以拦截那四个接口。本例中,我只想拦截查询的SQL,所以我选择拦截StatementHandler的query方法

    package org.apache.ibatis.executor.statement;
    
    import java.sql.Connection;
    import java.sql.SQLException;
    import java.sql.Statement;
    import java.util.List;
    import org.apache.ibatis.cursor.Cursor;
    import org.apache.ibatis.executor.parameter.ParameterHandler;
    import org.apache.ibatis.mapping.BoundSql;
    import org.apache.ibatis.session.ResultHandler;
    
    public interface StatementHandler {
        Statement prepare(Connection var1, Integer var2) throws SQLException;
    
        void parameterize(Statement var1) throws SQLException;
    
        void batch(Statement var1) throws SQLException;
    
        int update(Statement var1) throws SQLException;
    
        <E> List<E> query(Statement var1, ResultHandler var2) throws SQLException;
    
        <E> Cursor<E> queryCursor(Statement var1) throws SQLException;
    
        BoundSql getBoundSql();
    
        ParameterHandler getParameterHandler();
    }

    所以,@Signature注解中,type表示拦截的接口,method表示接口中的方法,而参数就是该方法的参数

    4.2、截图

  • 相关阅读:
    Ubuntu 16.09下iptables通过raw表实现日志输出和调试
    CentOS 6.9永久设置静态路由表以及路由表常用设置
    Linux下添加静态路由表设置网关出现SIOCADDRT: Network is unreachable的问题分析
    Linux下使用ISC DHCP可以实现动态推送静态路由表
    Linux下使用ping出现destination is unreachable的问题可能性
    树莓派(Debian)系统开启iptables的raw表实现日志输出
    MySQL时间戳与日期互转
    树莓派(Debian)系统设置了静态IP之后还会获取动态IP的问题解决(scope global secondary eth0)
    Linux下同一网段内的IP中两台主机通信不经过路由器(ARP)(转)
    OpenWrt包管理软件opkg的使用(极路由)
  • 原文地址:https://www.cnblogs.com/cjsblog/p/9015364.html
Copyright © 2011-2022 走看看