mybatis拦截器

温馨提示:本文章是基于springboot 2.4.2 ,mybatis 2.2.0 来实现的。项目能正常使用并且已经项目中用了PageHelper插件的可以参考本文章。

(1)先建一个mybatis的配置类

image

/**

* @description: TODO MybatisConfig类 (加载PageHelper的配置之后加载该配置,添加拦截器,保证执行顺序。)

* @author zouyuxian

* @date 2021/12/1 15:26

*/

@Configuration

@AutoConfigureAfter(PageHelperAutoConfiguration.class)

public class MybatisConfig {

@Resource

SqlSessionFactoryiotSqlSessionFactory;

@PostConstruct

public void addInterceptor(){

iotSqlSessionFactory.getConfiguration().addInterceptor(new MybatisInterceptor());

iotSqlSessionFactory.getConfiguration().setMapUnderscoreToCamelCase(true);

}

}

(2)mybatis拦截类

@Component

@Slf4j

@Intercepts({

// @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class}),

          @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.class})

})

public class MybatisInterceptorimplements Interceptor {

private static final Loggerlogger = LoggerFactory.getLogger(MybatisInterceptor.class);

private static final IntegerMAPPED_STATEMENT_INDEX =0;

private static final IntegerPARAM_OBJ_INDEX =1;

private static final IntegerROW_BOUNDS_INDEX =2;

private static final IntegerRESULT_HANDLER_INDEX =3;

private static final IntegerCACHE_KEY_INDEX =4;

private static final IntegerBOUND_SQL_INDEX =5;

private static final StringCOUNT_PRE ="_COUNT";

@Override

public Object plugin(Object target) {

return Plugin.wrap(realTarget(target),this);

}

@Override

public void setProperties(Properties properties0) {

}

@SuppressWarnings("unchecked")

public static T realTarget(Object target) {

if (Proxy.isProxyClass(target.getClass())) {

MetaObject metaObject = SystemMetaObject.forObject(target);

return realTarget(metaObject.getValue("h.target"));

}

return (T) target;

}

@Override

public Object intercept(Invocation invocation)throws Throwable {

Object[] args = invocation.getArgs();

Object parameter = args[PARAM_OBJ_INDEX];

if(null==parameter){

return invocation.proceed();

}

PageBean pageBean = vaildParamter(parameter);

if(null==pageBean){

return invocation.proceed();

}

MappedStatement ms = (MappedStatement) args[MAPPED_STATEMENT_INDEX];

RowBounds rowBounds = (RowBounds) args[ROW_BOUNDS_INDEX];

ResultHandler resultHandler = (ResultHandler) args[RESULT_HANDLER_INDEX];

Executor executor = (Executor) invocation.getTarget();

CacheKey cacheKey;

BoundSql boundSql;

String newSql =null;

//由于逻辑关系,只会进入一次

    if (args.length ==4) {

//四个参数走这里

        boundSql = ms.getBoundSql(parameter);

cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql);

//boundSql.getSql(),获取到sql之后,可以进行拼接修改

logger.info("四个参数的:"+newSql);

}else {

//六个参数走这里

        cacheKey = (CacheKey) args[CACHE_KEY_INDEX];

boundSql = (BoundSql) args[BOUND_SQL_INDEX];

//boundSql.getSql(),获取到sql之后,可以进行拼接修改

logger.info("六个个参数的:"+newSql);

}

MappedStatement newMappedStatement = setCurrentSql(ms,parameter,boundSql,newSql);

args[MAPPED_STATEMENT_INDEX] = newMappedStatement;

return executor.query(newMappedStatement, parameter, rowBounds, resultHandler, cacheKey, boundSql);

}

/*

* @Description : 重新设置MappedStatement
  • @URL :

  • @param mappedStatement

  • @param paramObj

  • @param boundSql

  • @param sql

  • @return : org.apache.ibatis.mapping.MappedStatement

  • @Author : zouyuxian

  • @Date : 2021/12/24 12:41

**/

private MappedStatement setCurrentSql(MappedStatement mappedStatement, Object paramObj,BoundSql boundSql,String sql) {

BoundSqlSource boundSqlSource =new BoundSqlSource(boundSql);

MappedStatement newMappedStatement = copyFromMappedStatement(mappedStatement, boundSqlSource);

MetaObject metaObject = MetaObject.forObject(newMappedStatement,

new DefaultObjectFactory(),new DefaultObjectWrapperFactory(),

new DefaultReflectorFactory());

metaObject.setValue("sqlSource.boundSql.sql", sql);

return newMappedStatement;

}

/*

* @Description :获取MappedStatement
  • @URL :

  • @param invo

  • @return : org.apache.ibatis.mapping.MappedStatement

  • @Author : zouyuxian

  • @Date : 2021/12/24 12:41

**/

private MappedStatement getMappedStatement(Invocation invo) {

Object[] args = invo.getArgs();

Object mappedStatement = args[MAPPED_STATEMENT_INDEX];

return (MappedStatement) mappedStatement;

}

/*

* @Description : 自定义私有SqlSource
  • @Author : zouyuxian

  • @Date : 2021/12/24 12:42

**/

private class BoundSqlSourceimplements SqlSource {

private BoundSqlboundSql;

private BoundSqlSource(BoundSql boundSql) {

this.boundSql = boundSql;

}

@Override

    public BoundSql getBoundSql(Object parameterObject) {

return boundSql;

}

}

/*

  • @Description :copyMappedStatement

  • @URL :

  • @param ms

  • @param newSqlSource

  • @return : org.apache.ibatis.mapping.MappedStatement

  • @Author : zouyuxian

  • @Date : 2021/12/24 12:42

**/

private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {

MappedStatement.Builder builder =new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource, ms.getSqlCommandType());

builder.resource(ms.getResource());

builder.fetchSize(ms.getFetchSize());

builder.statementType(ms.getStatementType());

builder.keyGenerator(ms.getKeyGenerator());

if (ms.getKeyProperties() !=null && ms.getKeyProperties().length >0) {

builder.keyProperty(ms.getKeyProperties()[0]);

}

builder.timeout(ms.getTimeout());

builder.parameterMap(ms.getParameterMap());

builder.resultMaps(ms.getResultMaps());

builder.resultSetType(ms.getResultSetType());

builder.cache(ms.getCache());

builder.flushCacheRequired(ms.isFlushCacheRequired());

builder.useCache(ms.isUseCache());

return builder.build();

}

3.总结,用了PageHelper插件,会先生成一个查询id_COUNT 的查询总数语句,先执行COUNT语句,然后才执行写的语句,在做这个的时候遇到重新setSql无效的问题,原先我是用的反射直接改boundSql的值,执行的sql还是原来的值,后来直接改的invocation[5]的值报了一个xxx_COUNT类型转换的错,最终查了很多文章和资料之后找到了解决方案:

image

参考文章指路:https://blog.csdn.net/zhuwei_clark/article/details/110958124

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容