zoukankan      html  css  js  c++  java
  • MyBatis Interceptor

    MyBatis的拦截器可以用于在以下对象及方法中拦截修改:

    • Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
    • ParameterHandler (getParameterObject, setParameters)
    • ResultSetHandler (handleResultSets, handleOutputParameters)
    • StatementHandler (prepare, parameterize, batch, update, query)

    每一个方法会对应不同的参数列表, 这些需要体现在Intercepts的Signature中

    配置

    除了实现Interceptor接口以外, 需要在项目中做以下配置

    application.yml

    增加对应的mybatis-config.xml, 因为现在还不支持在yml中配置plugin

    mybatis:
      type-aliases-package: com.compayn.proj.commons.api.dto
      mapper-locations: classpath:mapper/*.xml
      config-location: classpath:mybatis-config.xml
    

    mybatis-config.xml

    增加mybatis配置文件, 注意这里配置的拦截器, 其实际执行顺序是自下而上的

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd">
    
    <configuration>
        <settings>
            <setting name="..." value="true" />
        </settings>
    
        <plugins>
            <!-- The invocation order is bottom up -->
            <plugin interceptor="com.company.proj.commons.impl.interceptor.BaseInterceptor" />
        </plugins>
    
    </configuration>
    

      

    Interceptor实现

    一个简单的拦截器实现, 可以输出执行的sql, 以及执行时间.

    import org.apache.ibatis.executor.Executor;
    import org.apache.ibatis.executor.statement.StatementHandler;
    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;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.sql.Statement;
    import java.util.Properties;
    
    @Intercepts({
            @Signature(type = StatementHandler.class, method = "batch", args = { Statement.class}),
            @Signature(type = StatementHandler.class, method = "update", args = { Statement.class}),
            @Signature(type = StatementHandler.class, method = "query", args = { Statement.class, ResultHandler.class}),
            @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
            @Signature(type = Executor.class, method = "update", args = {MappedStatement.class,Object.class})})
    public class BaseInterceptor implements Interceptor {
        private static Logger logger = LoggerFactory.getLogger(BaseInterceptor.class);
    
        /**
         * 用于封装目标对象, 可以返回目标对象本身也可以返回一个它的代理, 这将决定是否会进行拦截
         */
        @Override
        public Object plugin(Object target) {
            if (target instanceof Executor) { // 仅当对象为Executor时, 才使用本插件
                return Plugin.wrap(target, this);
            } else {
                return target;
            }
        }
    
        /**
         * 用于配置本插件的相关属性
         */
        @Override
        public void setProperties(Properties properties) {
            // Do nothing
        }
    
        @Override
        public Object intercept(Invocation invocation) throws Throwable {
            long start = System.currentTimeMillis();
    
            Object target = invocation.getTarget(); //被代理对象
    
            if (target instanceof Executor) {
                MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
                Object parameter = invocation.getArgs()[1];
                BoundSql boundSql = mappedStatement.getBoundSql(parameter);
                String sql = boundSql.getSql();
                logger.info("SQL: {}", sql);
            }
    
            Object result = invocation.proceed();
            long duration = System.currentTimeMillis() - start;
            logger.info("Time elapsed: {}ms", duration);
            return result;
        }
    }
    

    代码说明

    @Intercepts 注解: 这个地方配置需要拦截的对象方法, 每个方法对应一个Signature, 这个Signature由对象类型, 方法名和参数组成, 方法名和参数可以直接参考这个对象的接口.

    Object plugin(Object target)接口: 用于封装目标对象, 可以返回目标对象本身也可以返回一个它的代理, 这将决定是否会进行拦截

    void setProperties(Properties properties)接口: 用于配置本插件的相关属性, 值可以通过Mybatis配置文件传入

    Object intercept(Invocation invocation) throws Throwable接口: 执行拦截的方法, 其中 invocation.getTarget() 可以看到实际被代理的对象, 根据对象类型不同, 可以读取这个对象方法的参数并进行需要的操作.

  • 相关阅读:
    js对象数组(JSON) 根据某个共同字段 分组
    一个 函数 用来转化esSearch 的range 条件
    关于 vuex 报错 Do not mutate vuex store state outside mutation handlers.
    android listview 重用view导致的选择混乱问题
    android SDK和ADT的更新
    Android中adb push和adb install的使用区别
    pycharm中添加扩展工具pylint
    su Authentication failure解决
    Putty以及adb网络调试
    有关android源码编译的几个问题
  • 原文地址:https://www.cnblogs.com/milton/p/12746436.html
Copyright © 2011-2022 走看看