mybatis interceptor(拦截器) 监控语句执行时间

公司没有运维,没有DBA,大家只管写SQL,能够查询出来结果就行,有时候也搞不清楚哪种写法更加的高效,最开始的时候没有数据量也没有性能的对比,当然大公司请忽略这个了,因为阿里云RDS自己有监控,DBA会优化sql,先看看简单的代码


import java.util.HashSet;
import java.util.Map;
import java.util.Properties;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
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.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;

@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, CacheKey.class, BoundSql.class}),
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class,
            ResultHandler.class})
    }
)
@Slf4j
public class TimerInterceptor implements Interceptor {

  @Override
  public Object intercept(Invocation invocation) throws Throwable {
    try {
      Object[] args = invocation.getArgs();
      MappedStatement ms = (MappedStatement) args[0];
      Object parameter = args[1];
      Object p;
      //这里的参数这样判断是因为加了@Param的和没有加的好像有点区别,调试的时候看到的
      if (parameter instanceof Map) {
        Map map = (Map) parameter;
        HashSet<Object> set = new HashSet<>();
        set.addAll(map.values());
        p = set;
      } else {
        p = parameter;
      }
      Object result;
      long start = System.currentTimeMillis();
      result = invocation.proceed();
      long end = System.currentTimeMillis();
      long cost = end - start;
      log.debug("[TimerInterceptor] execute [{}] cost [{}] ms, parameter:{}", ms.getId(), cost, p);
      if (cost > 2000) {//这里的时间根据情况设定,也可以写在配置文件里面
        log.warn("Sql语句执行时间超过2秒钟,请检查优化,方法:{},耗时:{}ms,参数:{}", ms.getId(), cost, p);
      }
      return result;
    } catch (Throwable r) {
      log.error(r.getMessage(), r);
    }
    return invocation.proceed();
  }

  @Override
  public Object plugin(Object target) {
    return Plugin.wrap(target, this);
  }

  @Override
  public void setProperties(Properties properties) {

  }
}

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容