项目中途遇到业务需求更改,在查询某张表时需要增加条件,由于涉及的sql语句多而且依赖其他服务的jar,逐个修改sql语句和接口太繁杂。项目使用mybatis框架,因此借鉴PageHelper插件尝试使用mybatis的Interceptor来实现改需求。
总体思路:
- 从BoundSql中获取sql,通过正则匹配替换表名为子查询REPLACE_TXT
- 添加子查询REPLACE_TXT 中需要用到的参数到mybatis参数列表中
- 添加参数与占位符映射,即添加ParameterMapping对象到ParameterMappings中,由于statement在执行时是按照ParameterMappings的元素索引定位占位符封装参数(即ParameterMappings中的第一个参数会封装到第一个占位符上),因此ParameterMappings中的参数顺序需要和占位符保持一致。其次ParameterMappings的元素个数需要和占位符个数保持一致。
- 为了保证该intercept在最后执行,使用AutoConfiguration将intercept添加到SqlSessionFactory的Configuration中,并在spring.factories文件中添加AutoConfiguration
- 未测试性能以及是否存在未知缺陷
1、Interceptor 代码实现
package org.cnbi.project.other.sql.intercept;
import cn.hutool.core.util.NumberUtil;
import com.cnbi.cloud.common.core.exception.ServiceException;
import com.github.pagehelper.Page;
import com.github.pagehelper.util.ExecutorUtil;
import com.github.pagehelper.util.MetaObjectUtil;
import org.apache.ibatis.builder.annotation.ProviderSqlSource;
import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.plugin.*;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.cnbi.project.other.sql.aop.PeriodHolder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @ClassName ParamInterceptor
* @Description 修改接口太繁琐,直接用mybatis拦截器对查询sql进行拦截,将期间参数注入sql
* @Author Wangjunkai
* @Date 2019/10/23 11:36
**/
@Intercepts({
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}),
@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.c