Mybatis拦截器介绍

一、Mybatis拦截器介绍

  Mybatis拦截器设计的思路是为了供用户灵活的实现自己的逻辑,而不动mybatis固有的逻辑,简而言之就是如果Mybatis是一只虾,我们要做的是将虾肉掏空,放入自己喜欢吃的东西进去,而依旧保持吓得壳身。通过Mybatis拦截器我们能拦截某些方法的调用,我们可以选择在这些被拦截方法执行前后加上我们自己的逻辑,达到丰富方法的效果;也可以在执行这些方法的时候拦截住,转而实现自己设计的方法,而最后不执行被拦截的方法。Mybatis中有很多核心对象,大致如下:

SqlSession 负责和数据库进行交互,实现完成常对数据操作的增删改查功能
Executor Mybatis执行器,调度的核心,负责SQL语句的生成和维护
StatementHandler 封装并操作Jdbc statement,例如设置参数,将statement结果集转化为List集合
ParameterHandler 负责将用户传递的参数转换为Jdbc statement所需要的参数进行传递
ResultSetHandler 负责将Jdbc返回的ResultSet结果集对象转换为List类型的集合
TypeHandler 负责将java数据类型和Jdbc数据类型之间的转换和映射
MappedStatement MappedStatement维护了一条mapper.xml文件里面 select 、update、delete、insert节点的封装
Configuration MyBatis所有的配置信息都维持在Configuration对象之中
BoundSql 表示动态生成的SQL语句以及相应的参数信息

 

 

 

 

 

 

 

 

 

 

 

Mybatis拦截器并不能拦截mybatis核心对象中所有方法,相反的,MyBatis拦截器可以拦截四个对象中方法,分别是:Executor、StatementHandler、ParameterHandler 和ResultSetHandler。

 1. Executor

Executor是mybatis核心接口,数据库增删改语句是通过Executor接口的update方法进行的,查询是通过query方法进行,代码如下:

public interface Executor {
    /*
    * 执行update/insert/delete
    * */
    int update(MappedStatement ms , Object paramter)throws SQLException;

    /*
    * 执行查询,先在缓存中查找
    * Mybatis提供了一个简单的逻辑分页使用类RowBounds(物理分页当然就是我们在sql语句中指定limit和offset值),在DefaultSqlSession提供的某些查询接口中我们可以看到RowBounds是作为参数用来进行分页的
    * */
    <E> List<E> query(MappedStatement ms , Object paramter , RowBounds rowBounds , ResultSetHandler resultSetHandler , CacheKey cacheKey , BoundSql boundSql)throws SQLException;

    /*
    * 执行查询
    * */
     <E> List<E> query(MappedStatement ms , Object paramter , ResultSetHandler resultSetHandler)throws SQLException;

     /*
     * 执行查询,结果放在Cursor里面
     * */
     <E> Cursor<E> queryCursor(MappedStatement ms , Object paramter)throws SQLException;
     
}

2. ParameterHandler

ParameterHandler用来设置参数规则,当StatementHandler使用prepare()方法后,接下来就是使用它来设置参数。所以如果有对参数做自定义逻辑处理的时候,可以通过拦截ParameterHandler来实现。ParameterHandler里面可以拦截的方法解释如下:

public interface ParameterHandler {
    /*
    * 设置参数规则的时候使用——PreparedStatement
    * */
    void setParamters(PreparedStatement ps) throws SQLException;
}

3. StatementHandler

StatementHandler负责处理Mybatis与JDBC之间Statement的交互。

 

public interface StatementHandler {
    /*
    * 从连接中获取一个Statement
    * */
    Statement prepare(Connection conn , Integer transactionTimeout)throws SQLException;

    /*
    * 设置statement执行里需要的参数
    * */
    void paramterize(Statement statement)throws SQLException;

    /**
     * 批量
     */
    void batch(Statement statement)
            throws SQLException;

    /**
     * 更新:update/insert/delete语句
     */
    int update(Statement statement)
            throws SQLException;

    /**
     * 执行查询
     */
    <E> List<E> query(Statement statement, ResultHandler resultHandler)
            throws SQLException;

    <E> Cursor<E> queryCursor(Statement statement)
            throws SQLException;
}

一般只拦截prepare方法。

在Mybatis里面RoutingStatementHandler是SimpleStatementHandler(对应Statement)、PreparedStatementHandler(对应PreparedStatement)、CallableStatementHandler(对应CallableStatement)的路由类,所有需要拦截StatementHandler里面的方法的时候,对RoutingStatementHandler做拦截处理就可以了,如下的写法可以过滤掉一些不必要的拦截类。

@Intercepts({
        @Signature(
                type = Statement.class ,
                method =  "prepare",
                args = {Connection.class , Integer.class}
        )
})
public class TableShardInterceptor implements Interceptor {
    /*
    * mybatis运行时要执行的拦截方法
    * */
    @Override
    public Object intercept(Invocation invocation ) throws Throwable{
        if(invocation.getTarget()instanceof RoutingStatementHandler){
            //to do 自己的逻辑
        }
        return invocation.proceed();
    }
    /*
    * target:拦截对象
    *
    * */
    @Override
    public Object plugin(Object target){
        // 当目标类是StatementHandler类型时,才包装目标类,否者直接返回目标本身,减少目标被代理的次数
        return (target instanceof RoutingStatementHandler)? Plugin.wrap(target,this):target;
    }
    //实现插件参数传递
    @Override
    public void setProperties(Properties properties){

    }


}

 4. ResultSetHandler

  ResultSetHandler用于对查询到的结果做处理。所以如果你有需求需要对返回结果做特殊处理的情况下可以去拦截ResultSetHandler的处理。ResultSetHandler里面常用拦截方法如下:

public interface ResultSetHandler {
    /*
    * 将statement执行后产生的结果集(可能有多个结果集)映射为结果表
    * */
    <E> List<E> handResultSets(Statement stmt)throws SQLException;
    <E> List<E> handleCursorResultSet(Statement stmt)throws SQLException;

    /*
    * 处理存储过程执行后的输出参数
    * */
    void handleOutputParameters(CallableStatement cs) throws SQLException;
}

至此,拦截器介绍由此结束。

部分内容参考自:https://blog.csdn.net/wuyuxing24/article/details/89343951

上一篇:android studio通过jdbc接口连mysql


下一篇:jdbc--Mysql异常问题总结