拦截 改写MySQL查询语句_SpringBoot 通过自定义 Mybatis 拦截器,实现 SQL 的改写

packagespcommon.config;importorg.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.*;import org.apache.ibatis.plugin.*;importorg.apache.ibatis.session.ResultHandler;importorg.apache.ibatis.session.RowBounds;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importjava.util.Properties;/*** 自定义 MyBatis 拦截器*/@Intercepts({@Signature(type= Executor.class, method = "query",

args= {MappedStatement.class, Object.class, RowBounds.class,ResultHandler.class})})public class MySqlInterceptor implementsInterceptor {private static final Logger logger= LoggerFactory.getLogger(MySqlInterceptor.class);/*** intercept 方法用来对拦截的sql进行具体的操作

*@paraminvocation

*@return*@throwsThrowable*/@Overridepublic Object intercept(Invocation invocation) throwsThrowable {

logger.info("执行intercept方法:{}", invocation.toString());

Object[] args=invocation.getArgs();

MappedStatement ms= (MappedStatement) args[0];

Object parameterObject= args[1];//id为执行的mapper方法的全路径名,如com.mapper.UserMapper

String id =ms.getId();//sql语句类型 select、delete、insert、update

String sqlCommandType =ms.getSqlCommandType().toString();//仅拦截 select 查询//if (!sqlCommandType.equals(SqlCommandType.SELECT.toString())) {//return invocation.proceed();//}

BoundSql boundSql=ms.getBoundSql(parameterObject);

String origSql=boundSql.getSql();

logger.info("原始SQL: {}", origSql);//组装新的 sql

String newSql = origSql + " limit 1";//重新new一个查询语句对象

BoundSql newBoundSql = newBoundSql(ms.getConfiguration(), newSql,

boundSql.getParameterMappings(), boundSql.getParameterObject());//把新的查询放到statement里

MappedStatement newMs = newMappedStatement(ms, newBoundSqlSqlSource(newBoundSql));for(ParameterMapping mapping : boundSql.getParameterMappings()) {

String prop=mapping.getProperty();if(boundSql.hasAdditionalParameter(prop)) {

newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop));

}

}

Object[] queryArgs=invocation.getArgs();

queryArgs[0] =newMs;

logger.info("改写的SQL: {}", newSql);returninvocation.proceed();

}/*** 定义一个内部辅助类,作用是包装 SQL*/

class BoundSqlSqlSource implementsSqlSource {privateBoundSql boundSql;publicBoundSqlSqlSource(BoundSql boundSql) {this.boundSql =boundSql;

}publicBoundSql getBoundSql(Object parameterObject) {returnboundSql;

}

}privateMappedStatement newMappedStatement (MappedStatement ms, SqlSource newSqlSource) {

MappedStatement.Builder builder= newMappedStatement.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());returnbuilder.build();

}

@OverridepublicObject plugin(Object target) {

logger.info("plugin方法:{}", target);if (target instanceofExecutor) {return Plugin.wrap(target, this);

}returntarget;

}

@Overridepublic voidsetProperties(Properties properties) {//获取属性//String value1 = properties.getProperty("prop1");

logger.info("properties方法:{}", properties.toString());

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值