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
package com.cjs.boot.interceptor; import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.session.ResultHandler; import java.sql.Statement;
import java.util.Properties; @Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class})})
public class SqlStatementInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
long startTime = System.currentTimeMillis();
try {
return invocation.proceed();
} finally {
long endTime = System.currentTimeMillis(); StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
BoundSql boundSql = statementHandler.getBoundSql();
String sql = boundSql.getSql();
sql = sql.replace("\n", "").replace("\t", "").replaceAll("\\s+", " "); log.info("执行SQL: [{}]花费{}ms", sql, (endTime - startTime)); }
} @Override
public Object plugin(Object target) {
return Plugin.wrap(target, this);
} @Override
public void setProperties(Properties properties) { }
}
2、配置SqlSessionFactory
package com.cjs.boot.config; import com.cjs.boot.interceptor.SqlStatementInterceptor;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import javax.annotation.Resource;
import javax.sql.DataSource; @Configuration
public class MyBatisConfig { @Resource
private DataSource dataSource; @Bean
public SqlSessionFactory sqlSessionFactory() throws Exception {
SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
sqlSessionFactoryBean.setDataSource(dataSource);
sqlSessionFactoryBean.setPlugins(new Interceptor[]{new SqlStatementInterceptor()});
PathMatchingResourcePatternResolver pathMatchingResourcePatternResolver = new PathMatchingResourcePatternResolver();
sqlSessionFactoryBean.setMapperLocations(pathMatchingResourcePatternResolver.getResources("classpath:mapper/*Mapper.xml"));
sqlSessionFactoryBean.setTypeAliasesPackage("com.cjs.boot.domain.entity");
return sqlSessionFactoryBean.getObject();
} }
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打印SQL执行时间的更多相关文章
- mybatis 打印sql 语句
拦截器 package com.cares.asis.mybatis.interceptor; import java.text.DateFormat; import java.util.Date; ...
- mybatis 打印sql log配置
mybatis 打印sql log, 方便调试.如何配置呢? log4j.xml : <!-- 打印sql start --> <appender name="IBatis ...
- 【spring boot】【mybatis】spring boot中mybatis打印sql语句
spring boot中mybatis打印sql语句,怎么打印出来?[参考:https://www.cnblogs.com/sxdcgaq8080/p/9100178.html] 在applicati ...
- 【记录】spring/springboot 配置mybatis打印sql
======================springboot mybatis 打印sql========================================== 方式 一: ##### ...
- mybatis 打印 sql
该文中使用的log框架为logback myBatis3.0.6左右的版本时 打印sql的时候只需要配置如下属性: <logger name="java.sql.Connection& ...
- (后端)SpringBoot中Mybatis打印sql(转)
原文地址:https://www.cnblogs.com/expiator/p/8664977.html 如果使用的是application.properties文件,加入如下配置: logging. ...
- SpringBoot中Mybatis打印sql
原文:https://www.cnblogs.com/expiator/p/8664977.html 如果使用的是application.properties文件,加入如下配置: logging.le ...
- mybatis 打印SQL
如果使用的是application.properties文件,加入如下配置: #打印SQL logging.level.com.jn.ssr.supererscuereporting.dao=debu ...
- logback mybatis 打印sql语句
logbac.xml 文件的基础配置参考的园友的 http://www.cnblogs.com/yuanermen/archive/2012/02/13/2349609.html 然后hibernat ...
随机推荐
- SpringMVC返回json是设置编辑等消息头,消息头信息介绍(respone.setHeader,这个从网上获取)
1. SpringMVC中设置消息头,例子如下: ? 因为上面的代码没有添加该文件的编码说明 , WEB应用程序在将jsp翻译成class文件时 , 把该字符串的内容按默认的保存方式指定的编码ASC ...
- 【翻译】在Ext JS和Sencha Touch中创建自定义布局
原文:Creating Custom Layouts in Ext JS and Sencha Touch 布局系统是Sencha框架中最强大和最独特的一部分.布局会处理应用程序中每个组件的大小和位置 ...
- linux测试noatime对文件访问时间的影响
linux测试noatime对文件访问时间的影响 文件(如abc)有3个时间: # stat abc Access: 2015-04-16 19:30:13.665970572 +0800 Modif ...
- Adobe Premiere 基本使用
第一节 Premiere概述 1.1概述 Premiere是Adobe公司出品的一款用于进行影视后期编辑的软件,是数字视频领域普及程度最高的编辑软件之一.对于学生媒体而言,Premiere完全可以 ...
- LeetCode之“树”:Binary Tree Level Order Traversal && Binary Tree Level Order Traversal II
Binary Tree Level Order Traversal 题目链接 题目要求: Given a binary tree, return the level order traversal o ...
- Android中使用SVG矢量图(一)
SVG矢量图介绍 首先要解释下什么是矢量图像,什么是位图图像? 1.矢量图像:SVG (Scalable Vector Graphics, 可伸缩矢量图形) 是W3C 推出的一种开放标准的文本式矢量图 ...
- SpriteBuilder中同父节点的显示顺序
如下图: 到目前为止,GameScene依赖于节点在SpriteBuilder中的顺序去决定其绘制的顺序. level content(_levelNode)被首先绘制,然后GameMenuLayer ...
- Zeromq自连接错误
Zeromq自连接错误(金庆的专栏)Zeromq消息中间件开发的服务器和客户端不必按顺序启动,客户端可以在服务器开启之前启动.这是Zmq特别好用的一大特性.利用该特性,网游各功能服务器可以任意重启,实 ...
- 安卓学习笔记--已root设备应用请求root权限
网上查到的方法 Process process = null; DataOutputStream os = null; try { String cmd = "chmod 777 " ...
- NOSQL schema创建原则
(1)数据规模 Bigtable类数据库系统(HBase,Cassandra等)是为了解决海量数据规模的存储需要设计的.这里说的海量数据规模指的是单个表存储的数据量是在TB或者PB规模,单个表是由千亿 ...