转载

mybatis 的进阶使用拦截器

文章思路

学一个东西我们首先要弄清楚它的使用场景 ,不然毫无意义。下面首先介绍 mybatis 插件的使用场景,然后再介绍如何使用,最后是它的原理 。

使用场景

  1. 首先是网上都在说的分页插件,这个已经有人实现了,可以使用 PageHelper 插件,我们可以学习它怎么做的,但没必要重复造轮子,直接用就可以了
  2. 使用 mybatis 的时候发现如果是 PrepareStatement 的时候 ,sql 语句和参数是分开的,查找问题时非常不方便,这时候可以自定义插件把整合后的 sql 打印在控制台上。当然生产上需要关闭这个功能,因为不可能把大量的 sql 打印在日志文件中。
  3. 统计慢查询,可以用 mybatis 插件,设置一个慢查询阈值,把慢的 select 查询发送到消息中间件或存储在 mongodb 等,然后在页面做一个慢查询可视化来监控慢查询。
  4. 数据权限,这个我在项目中用过,可以使用 jsqlParser 来增加 sql 根据当前登录用户来追加查询条件,而不用硬编码在 sql 语句中。

如何使用

实现 org.apache.ibatis.plugin.Interceptor 接口,并指明要拦截 Mybatis 哪个类的哪个方法,然后把其注册到 mybatis 插件中就可以了。

Mybatis拦截器只能拦截Executor、ParameterHandler、StatementHandler、ResultSetHandler四个对象里面的方法。

可拦截对象 解释
Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所需要的参数
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合
ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合;

快速使用,打印查询方法执行时间

  1. 定义拦截器
  2. 注册到 plugins 中,可以注册多个
@Intercepts(
        // 拦截 Executor.query 方法,不是查缓存那个
        @Signature(type = Executor.class,method = "query",args = {MappedStatement.class,Object.class, RowBounds.class, ResultHandler.class})
)
@Slf4j
public class TimeSpendInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StopWatch stopWatch = new StopWatch();stopWatch.start();
        // Invocation 的参数是看拦截的方法来的,这里 query 方法第一个参数是语句对象
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        String id = mappedStatement.getId();
        Object proceed = null;
        try {
            proceed =  invocation.proceed();
        }finally {
            stopWatch.stop();
            log.info("sqlId:"+id+" 执行时间为:"+stopWatch.getTime()+" ms");
        }
        return proceed;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target,this);
    }
}
@Configuration
public class MybatisConfig {
    @Bean("timeSpendInterceptor")
    public Interceptor interceptor2(){
        return new TimeSpendInterceptor();
    }
}

最后成果:

[ sqlId:com.sanri.test.testmybatis.mapper.BatchMapper.selectAll 执行时间为:548 ms ]

完整项目地址

https://gitee.com/sanri/example/tree/master/test-mybatis

一些小推广

Excel 通用导入导出,支持 Excel 公式

https://blog.csdn.net/sanri1993/article/details/100601578

使用模板代码 ,从数据库生成代码 ,及一些项目中经常可以用到的小工具

https://blog.csdn.net/sanri1993/article/details/98664034
原文  https://segmentfault.com/a/1190000020376692
正文到此结束
Loading...