Mybatis拦截器动态追加sql语句

拦截器介绍
MyBatis提供了一种插件(plugin)的功能,虽然叫做插件,但其实这是拦截器功能。

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
ParameterHandler (getParameterObject, setParameters)
ResultSetHandler (handleResultSets, handleOutputParameters)
StatementHandler (prepare, parameterize, batch, update, query)
我们看到了可以拦截Executor接口的部分方法,比如update,query,commit,rollback等方法,还有其他接口的一些方法等。

总体概括为:

拦截执行器的方法
拦截参数的处理
拦截结果集的处理
拦截Sql语法构建的处理

拦截器使用
配置文件添加

? <plugins>
? ? <plugin interceptor="com.uv.interceptor.MybatisInterceptor">
? ? ? <property name="name" value="test"></property>
? ? </plugin>
? </plugins>

MybatisInterceptor

import java.lang.reflect.Field;
import java.sql.Connection;
import java.util.Properties;
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.plugin.Signature;
import org.apache.ibatis.reflection.DefaultReflectorFactory;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.SystemMetaObject;
?
/*
?* @author cs
?* @date 2018/10/4 18:16
?*
?*/
?
//拦截StatementHandler类中参数类型为Statement的 prepare 方法
//即拦截 Statement prepare(Connection var1, Integer var2) 方法
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class MybatisInterceptor implements Interceptor {
?
?
? ? @Override
? ? public Object intercept(Invocation invocation) throws Throwable {
?
? ? ? ? StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
? ? ? ? //通过MetaObject优雅访问对象的属性,这里是访问statementHandler的属性;:MetaObject是Mybatis提供的一个用于方便、
? ? ? ? //优雅访问对象属性的对象,通过它可以简化代码、不需要try/catch各种reflect异常,同时它支持对JavaBean、Collection、Map三种类型对象的操作。
? ? ? ? MetaObject metaObject = MetaObject
? ? ? ? ? ? .forObject(statementHandler, SystemMetaObject.DEFAULT_OBJECT_FACTORY, SystemMetaObject.DEFAULT_OBJECT_WRAPPER_FACTORY,
? ? ? ? ? ? ? ? new DefaultReflectorFactory());
? ? ? ? //先拦截到RoutingStatementHandler,里面有个StatementHandler类型的delegate变量,其实现类是BaseStatementHandler,然后就到BaseStatementHandler的成员变量mappedStatement
? ? ? ? MappedStatement mappedStatement = (MappedStatement) metaObject.getValue("delegate.mappedStatement");
? ? ? ? //id为执行的mapper方法的全路径名,如com.uv.dao.UserMapper.insertUser
? ? ? ? String id = mappedStatement.getId();
? ? ? ? //sql语句类型 select、delete、insert、update
? ? ? ? String sqlCommandType = mappedStatement.getSqlCommandType().toString();
? ? ? ? //数据库连接信息
// ? ? ? ?Configuration configuration = mappedStatement.getConfiguration();
// ? ? ? ?ComboPooledDataSource dataSource = (ComboPooledDataSource)configuration.getEnvironment().getDataSource();
// ? ? ? ?dataSource.getJdbcUrl();
?
? ? ? ? BoundSql boundSql = statementHandler.getBoundSql();
? ? ? ? //获取到原始sql语句
? ? ? ? String sql = boundSql.getSql();
? ? ? ? String mSql = sql + " limit 2";
? ? ? ? //通过反射修改sql语句
? ? ? ? Field field = boundSql.getClass().getDeclaredField("sql");
? ? ? ? field.setAccessible(true);
? ? ? ? field.set(boundSql, mSql);
?
? ? ? ? return invocation.proceed();
? ? }
?
? ? @Override
? ? public Object plugin(Object target) {
? ? ? ? return Plugin.wrap(target, this);
? ? }
?
? ? @Override
? ? public void setProperties(Properties properties) {
? ? ? ? //此处可以接收到配置文件的property参数
? ? ? ? System.out.println(properties.getProperty("name"));
? ? }
?
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值