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("\n", "").replace("\t", "").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、截图
相关文章
- Mybatis进阶学习笔记——输入映射
- ssm(Spring+Spring mvc+mybatis)Service层实现类——DeptServiceImpl
- Mybatis+mysql动态分页查询数据案例——Mybatis的配置文件(mybatis-config.xml)
- 深入浅出Mybatis系列(十)---SQL执行流程分析(源码篇)(转)
- mybatis进行分页,使用limit
- Java_myBatis_一对多映射
- mybatis中传入String类型参数异常
- Java_myBatis_XML代理_动态SQL
- Atitit sql查询语法 SQL SELECT完整语法3 1.SELECT语法3 2.FROM子句5 3.WHERE子句6 下面两张表将在后面使用到7 1.比较运算符7 2.逻辑
- Atitit 读取数据库的api orm SQL Builder sql对比 目录 1.1. 提高生产效率的 ORM 和 SQL Builder1 1.2. SQL Builder 在 SQL
- Atitit mybatis使用简明教程 目录 1.1. Mybatis.xml 配置文件1 1.2. Datamp.xml mapper文件主要作用是分模块放sql语句2 1.3. 查询
- Atitit sql的执行功能 目录 1. 主要流程1 1.1. 获取conn,执行sql取得结果,1 1.2. Orm类的执行(hb mybatis为例1 2. 常见sql执行框架与类库1
- mybatis 批量插入值的sql
- 【MyBatis笔记10】Mybatis中几个动态SQL标签和内置参数
- 【项目实战】MyBatis映射文件中的动态SQL
- MyBatis快速入门——第四章、mybatis动态sql_if_choose_when
- 【SQL干货】一条sql查出来全国空气质量排名
- [DB][mybatis]MyBatis mapper文件引用变量#{}与${}差异
- 006-springboot2.0.4 配置log4j2,以及打印mybatis的sql
- SpringBoot中Mybatis打印sql
- Mybatis—动态SQL
- JavaEE——Spring学习笔记05【Mybatis的逆行工程】
- Spring+SpringMVC+Mybatis(开发必备技能)04、mybatis自动生成mapper_dao_model(包含工具与视频讲解) 纯绿色版本、配套使用视频,100%运行成功
- MyBatis之工作原理,简单实体的增加、修改、删除、查询_Mybatis-原理总结
- mybatis里mapper.xml中SQL语句if语句嵌套if语句
- mybatis plus之自定义SQL查询