因工作需要,小编近期基于mybatis拦截器开发了一款简易影子表自动切换插件,可以根据配置实现动态修改表名,即将对原source table表的操作自动切换到对target table表的操作。该插件既可以支持对简单的单表操作,也可以支持复杂的多表联合操作。
源码地址:mybatis影子表切换插件
下面来说说如何实现mybatis以自定义插件?
1. MyBatis核心部件
从MyBatis代码实现的角度来看,MyBatis的主要的核心部件有以下几个:
name description
SqlSession 作为MyBatis工作的主要顶层API,表示和数据库交互的会话,完成必要数据库增删改查功能
Executor MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护
StatementHandler 封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数、将Statement结果集转换成List集合
ParameterHandler 负责对用户传递的参数转换成JDBC Statement 所需要的参数
ResultSetHandler 负责将JDBC返回的ResultSet结果集对象转换成List类型的集合
TypeHandler 负责java数据类型和jdbc数据类型之间的映射和转换
MappedStatement MappedStatement维护了一条节点的封装
SqlSource 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回
BoundSql 表示动态生成的SQL语句以及相应的参数信息
Configuration MyBatis所有的配置信息都维持在Configuration对象之中
2. MyBatis核心部件的层次结构关系
3. 如何扩展?
基于MyBatis Interceptor插件机制
- 拦截器(Interceptor)在 MyBatis 中被当做插件(plugin)对待,官方文档提供了Executor(拦截执行器的方法),ParameterHandler(拦截参数的处理),ResultSetHandler(拦截结果集的处理),StatementHandler(拦截Sql语法构建的处理)共4种,并且提示“这些类中方法的细节可以通过查看每个方法的签名来发现,或者直接查看MyBatis发行包中的源代码”
- 拦截器的使用场景主要是更新数据库的通用字段,分库分表,加解密等的处理
- 我们使用Interceptor机制对执行的Sql进行拦截并追加逻辑,示例代码如下:
/**
* @author zhangjb
* @ClassName: MyInterceptor <br>
* @Description: 测试mybatis拦截器 <br>
* <p>
* 拦截方法 {@link org.apache.ibatis.executor.statement.StatementHandler#prepare(Connection, Integer)}
*/
@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MyInterceptor implements Interceptor {
.....
@Override
public Object intercept(Invocation invocation) throws Throwable {
try {
// do something
} catch (Throwable throwable) {
log.warn("MyInterceptor: {}", Throwables.getStackTraceAsString(throwable));
}
return invocation.proceed();
}
}
......
}
4. 关于兼容性
另外还需要注意的是mybatis-spring、mybatis、spring这三个包的兼容性,官方给出的兼容方案如下: