MyBatis拦截器

MyBatis拦截器作用


Mybatis可以在执行sql语句的过程中,织入一些拦截器,在不同的节点修改修改一些执行过程中的关键属性,从而影响SQL的生成、执行和返回结果。

MyBatis拦截器提供的扩展点


拦截执行器方法

org.apache.ibatis.executor.Executor

public interface Executor {
 
  ResultHandler NO_RESULT_HANDLER = null;
 
  int update(MappedStatement ms, Object parameter) throws SQLException;
 
  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;
 
  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;
 
  <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;
 
  List<BatchResult> flushStatements() throws SQLException;
 
  void commit(boolean required) throws SQLException;
 
  void rollback(boolean required) throws SQLException;
 
  CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);
 
  boolean isCached(MappedStatement ms, CacheKey key);
 
  void clearLocalCache();
 
  void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);
 
  Transaction getTransaction();
 
  void close(boolean forceRollback);
 
  boolean isClosed();
 
  void setExecutorWrapper(Executor executor);
 
}

拦截SQL语法构建处理

org.apache.ibatis.executor.statement.StatementHandler

public interface StatementHandler {
  // 创建JDBC Statement对象,并完成Statement对象的属性设置
  Statement prepare(Connection connection, Integer transactionTimeout)
      throws SQLException;
  // 使用MyBatis中的ParameterHandler组件为PreparedStatement和CallableStatement参数占位符设置值。
  void parameterize(Statement statement)
      throws SQLException;
  // 将SQL命令添加到批处量执行列表中。
  void batch(Statement statement)
      throws SQLException;
  // 调用Statement对象的execute()方法执行更新语句,例如UPDATE、INSERT、DELETE语句。
  int update(Statement statement)
      throws SQLException;
  // 执行查询语句,并使用ResultSetHandler处理查询结果集。
  <E> List<E> query(Statement statement, ResultHandler resultHandler)
      throws SQLException;
  // 带游标的查询返回Cursor对象。
  <E> Cursor<E> queryCursor(Statement statement)
      throws SQLException;
  // 获取Mapper中配置的SQL信息,BoundSql封装了动态SQL解析后的SQL文本和参数映射信息。
  BoundSql getBoundSql();
  // 获取ParameterHandler实例。
  ParameterHandler getParameterHandler();
}

拦截参数处理
org.apache.ibatis.executor.parameter.ParameterHandler

public interface ParameterHandler {
 
  Object getParameterObject();
 
  void setParameters(PreparedStatement ps) throws SQLException;
}

拦截结果集处理
org.apache.ibatis.executor.resultset.ResultSetHandler

public interface ResultSetHandler {
 
  <E> List<E> handleResultSets(Statement stmt) throws SQLException;
 
  <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;
 
  void handleOutputParameters(CallableStatement cs) throws SQLException;
 
}

各种拦截器的关系图

MyBatis拦截器用法

  • 拦截器提供的注解

@Intercepts
作用:标识当前类为拦截器类

@Signature
作用:
type:就是指定拦截器类型(ParameterHandler ,StatementHandler,ResultSetHandler )
method:是拦截器类型中的方法,不是自己写的方法
args:是method中方法的入参

MyBatis拦截器入门例子

@Slf4j
@Component
@Intercepts(value = {
        @Signature(type = ResultSetHandler.class, method = "handleResultSets", args = {Statement.class})
})
public class FirstInterceptor implements Interceptor {
 
    /**
     * 拦截方法逻辑
     * 这里主要是通过反射去获取要执行的SQL相关信息,然后进行操作
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
 
        // 代理方法
        log.info("=============== method = " + invocation.getMethod().getName());
        // 代理方法参数
        Object[] args = invocation.getArgs();
        Statement statement = (Statement) args[0];
        // 被代理的对象
        log.info("=============== args = " + invocation.getTarget());
        // 执行目标方法
        Object result = invocation.proceed();
        log.info("=============== result = " + result);
        return result;
    }
 
    /**
     * 生成MyBatis拦截器代理对象
     * @param target
     * @return
     */
    @Override
    public Object plugin(Object target) {
        if (target instanceof ResultSetHandler) {
            return Plugin.wrap(target, this);
        }
 
        return target;
    }
 
    /**
     * 设置插件属性(直接通过Spring的方式获取属性,所以这个方法一般也用不到)
     * 项目启动的时候数据就会被加载
     * @param properties
     */
    @Override
    public void setProperties(Properties properties) {
 
    }
}

结果:

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

推荐阅读更多精彩内容