Mybatis插件使用-统计sql执行时间
背景介绍:最近由于产品数据量较大,sql执行十分低效,正在做数据库优化,所以想在日志中看到每个sql执行的时间,以方便针对性的优化。
查找相关资料,了解到Mybatis有一款插件,是基于interceptor来实现的,可以在拦截器中来输出每个sql的执行时间,配置方便且简单,经过自测可用。
1、在dao的配置文件中,在sqlSessionFactory配置项里添加插件依赖:
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatis-config.xml" />
<property name="mapperLocations" value="classpath:/sqlmap/*Mapper.xml" />
<property name="dataSource" ref="dataSource" />
<property name="plugins">
<array>
<!-- 基于拦截器的实现,配置拦截器所在工程的全路径 -->
<bean id="sqlStatementInterceptor" class="com.**.interceptor.SqlStatementInterceptor"/>
</array>
</property>
</bean>
2、在工程com.**.interceptor包路径下添加SqlStatementInterceptor.java,具体代码如下:
/**
* Mybatis SQL拦截器,记录每个sqlId对应的执行时间
*
* @author yehaixiao
* @date 2017-09-07
*/
@Intercepts(value = {
@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 }),
@Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class,
RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class }) })
public class SqlStatementInterceptor implements Interceptor {
private static Logger logger = Logger.getLogger(SqlStatementInterceptor.class); @Override
public Object intercept(Invocation invocation) {
MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
// sqlId为mapper文件中定义的id,例如:com.**.dao.**Mapper.selectByPrimaryKey
String sqlId = mappedStatement.getId();
// 开始时间
long start = System.currentTimeMillis();
try {
return invocation.proceed();
} catch (Exception e) {
logger.error(sqlId + "执行失败!", e);
return null;
} finally {
long end = System.currentTimeMillis();
long time = end - start;
StringBuilder str = new StringBuilder();
str.append(sqlId);
str.append(": ");
str.append("cost time ");
str.append(time);
str.append(" ms.");
String sqlInfo = str.toString();
logger.debug(sqlInfo);
}
} @Override
public Object plugin(Object arg0) {
return Plugin.wrap(arg0, this);
} @Override
public void setProperties(Properties arg0) { }
}
说明:自定义的拦截器实现了org.apache.ibatis.plugin.Interceptor,Interceptor中有三个方法:
public abstract interface Interceptor {
public abstract Object intercept(Invocation paramInvocation) throws Throwable;
public abstract Object plugin(Object paramObject);
public abstract void setProperties(Properties paramProperties);
}
我们主要实现了intercept方法,入参是一个Invocation,Invocation的内部结构如下所示:
第一个参数是长度为4的args数组,数组的第一个参数是一个MappedStatement,其实这个就是执行一个sql对应的对象,该对象中有个getId,获取到的结果就是mapper文件中sql定义的id,这样就很容易明白自定义的拦截器里intercept方法里第一句话含义。
直到现在,相关的配置、代码以及说明全都结束,在执行sql的时候,日志中可以看到如下输出: 
Mybatis插件使用-统计sql执行时间的更多相关文章
- Mybatis插件Plugin
Mybatis开源Plugin中最熟知的pagehelper,重点made in China 很多人开始用pagehelper时候,肯定很纳闷,以mysql为例,明明没有加limit语句,为什么打印出 ...
- MyBatis7:MyBatis插件及示例----打印每条SQL语句及其执行时间
Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用 Executor(update.q ...
- MyBatis 插件 : 打印 SQL 及其执行时间
Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用: Executor(update. ...
- MyBatis插件及示例----打印每条SQL语句及其执行时间
Plugins 摘一段来自MyBatis官方文档的文字. MyBatis允许你在某一点拦截已映射语句执行的调用.默认情况下,MyBatis允许使用插件来拦截方法调用 Executor(update.q ...
- Mybatis插件,能做的事情真的很多
大家好,我是架构摆渡人.这是实践经验系列的第九篇文章,这个系列会给大家分享很多在实际工作中有用的经验,如果有收获,还请分享给更多的朋友. Mybatis是我们经常用的一款操作数据库的框架,它的插件机制 ...
- 统计sql语句执行效率
--统计sql语句执行效率SELECT (total_elapsed_time / execution_count)/1000 N'平均时间ms' ,total_elapsed_time/1000 N ...
- Mybatis插件机制以及PageHelper插件的原理
首先现在已经有很多Mybatis源码分析的文章,之所以重复造轮子,只是为了督促自己更好的理解源码. 1.先看一段PageHelper拦截器的配置,在mybatis的配置文件<configurat ...
- 动手实践Mybatis插件
前言 Mybatis的插件开发过程的前提是必须要对Mybatis整个SQL执行过程十分熟悉,这样才能正确覆盖源码保证插件运行,总的来说Mybatis的插件式一种侵入式插件,使用时应该十分注意. 在之前 ...
- mybatis插件机制
目录 mybatis插件机制 主要 类/接口 和 方法 mybatis插件机制实现 mybatis插件机制 mybatis的插件机制使用动态代理实现,不了解的朋友请先了解代理模式和动态代理:插件本质是 ...
随机推荐
- 当有多个form表单请求时如何处理?
问题:当有多个表单请求时如何处理?两种获取form表单 name属性值来区分是哪一个form表单.问题:如何获取name的值呢?<form name="myForm" met ...
- [proposal][app]Watch your time!
[Motivation] 很多时候,我们要去某个地方,尤其是第一次去的时候,都不知道什么时候出发,留出的时间够不够,会不会早到或者晚到.虽然地图软件能给出一些粗略的步行,公交,或者出租时间估计,但是每 ...
- 在推送提交之后阻止Azure DevOps (TFS)持续集成
在Azure DevOps服务器上配置生成定义时,可以配置连续集成(CI)生成.每次签入或提交到源代码库时都会自动运行一个CI构建.这种机制允许开发人员启动一个自动化的过程,例如编译和部署构建.这是一 ...
- dot net core 使用 IPC 进程通信
本文告诉大家如何使用dot net core 和其他进程进行通信 一般都是使用 WCF 或 remoting 做远程通信,但是 dot net core 不支持 WCF 所以暂时我就只能使用 管道通信 ...
- C#Datetimepicker出现问题及解决方法
前几天公司用的物料管理系统出现了一个很奇怪的问题,具体的现象是:10月31号的那天,物流部的人因为之前的问题,需要将之前已经结转的9月份取消结转. ,当操作人员将10改变为9的时候,出现问题了.程序直 ...
- Spring IOC 容器源码分析 - 创建原始 bean 对象
1. 简介 本篇文章是上一篇文章(创建单例 bean 的过程)的延续.在上一篇文章中,我们从战略层面上领略了doCreateBean方法的全过程.本篇文章,我们就从战术的层面上,详细分析doCreat ...
- 阿里云ECS 介绍
1.阿里云产品概述 1 2.阿里云基础架构介绍 2 3. ECS产品概念和功能 6 4. ECS运维管理和API 12 1.阿里云产品概述 2.阿里云基础架构介绍 ECS 主要有五个主要的组成部分 作 ...
- java变量初始化顺序
第一次实例化一个类时,初始化优先顺序为: 1.父类中的静态成员变量和静态代码块初始化 2.本类中的静态成员变量和静态代码块初始化 3.父类中的实例成员初始化 4.父类中的构造方法 5.本类中的实例成员 ...
- fatal: LF would be replaced by CRLF in index.html
进入项目目录,在.git文件夹下打开config配置文件,添加上下面两句话: autocrlf = false safecrlf = false 即可
- 不同Mesh技术的比较-总结版
引言 在过去的几年里,Mesh 网络逐渐变得流行,随之会有越来越多的无线产品面世.Mesh 网络技术作为一种无线自组网技术是物联网的核心技术.物联网的概念现在也逐渐贴近人们的生活, 据预测 2011 ...