mybatis拦截器的一些使用

一、拦截sql

package com.demo.mybatis;

import org.apache.ibatis.executor.keygen.SelectKeyGenerator;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.Properties;

@Intercepts(
        {
                @Signature(
                        type = StatementHandler.class,
                        method = "prepare",
                        args = {
                                Connection.class,
                                Integer.class
                        }
                )
        }
)
@Component
public class MybatisInterceptor implements Interceptor {

    private static final Logger logger = LoggerFactory.getLogger(MybatisInterceptor.class);

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
        MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");

		// 当前执行方法的全限定名
        String id = mappedStatement.getId();
        logger.info("mappedStatement.getId() : {}" , id);
        Class<?> aClass = Class.forName(id.substring(0, id.lastIndexOf(".")));
        String methodName = id.substring(id.lastIndexOf(".") + 1);
        for (Method method : aClass.getDeclaredMethods()) {
            if (method.getName().equals(methodName)) {
                BoundSql boundSql = statementHandler.getBoundSql();
                String sql = boundSql.getSql();
                logger.info("拦截到的sql : {}", sql);
            }
        }
        return invocation.proceed();
    }

    /**
     * 判断是否拦截这个类型的对象,然后决定返回一个代理对象还是原对象
     * 判断一下对象本身,是本插件要拦截的对象时才执行wrap方法,否则的话,直接返回目标本身
     */
    @Override
    public Object plugin(Object target) {
        if (target instanceof StatementHandler) {
            return Plugin.wrap(target, this);
        }
        return target;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

拦截结果如下:
在这里插入图片描述

二、拦截selectKey标签中的sql

1、mapper.xml如下
mybatis拦截器的一些使用_第1张图片
2、拦截器改造
mybatis拦截器的一些使用_第2张图片
当我们获取到的KeyGenerator为SelectKeyGenerator时,即可以通过反射来获取到具体的sql语句进行拦截;

3、实际拦截结果:
在这里插入图片描述

三、自定义

当然,我们也可以通过mybatis提供的反射类工具去拦截一些自己想拦截的东西:

MetaObject metaObject = MetaObject.forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY, new DefaultReflectorFactory());
Object value = metaObject.getValue("");

其中字符串入参可以通过调试去定位到具体的位置,再把路径放进去即可,如图所示:
mybatis拦截器的一些使用_第3张图片
mybatis拦截器的一些使用_第4张图片
一步步调试即可,定制一些个性化需求

你可能感兴趣的:(mybatis,java,spring,boot,开发语言,数据库)