自定义Mybatis拦截器 与PageHelper插件冲突问题

本文介绍了在使用自定义Mybatis拦截器时遇到与PageHelper插件冲突的问题。当项目同时使用两者时,自定义拦截器会失效。通过分析,发现原因是PageHelper的分页拦截器在其调用后未继续传递invocation.proceed()。为解决这个问题,提出了将自定义拦截器置于PageInterceptor之后的方法,即不在Spring中管理自定义拦截器,而是手动在启动时将其添加到拦截器链的末尾,并确保拦截器拦截相同的目标方法,以使执行顺序生效。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

话不多说上代码

这是自定义的mybatis插件拦截器,用来截取查询的sql


@Slf4j
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class ExamplePlugin implements Interceptor {

    /**
     * 进行拦截的时候要执行的方法
     * @param invocation
     * @return
     * @throws Throwable
     */
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        System.out.println("====intercept======");

        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = statementHandler.getBoundSql();
        //获取到原始sql语句
        String sql = boundSql.getSql();
        log.info(sql);
        DataSourceContextHolder.setDB(sql);
        Object proceed = invocation.proceed();
        return proceed;

    }

    @Override
    public Object plugin(Object target) {
        System.out.println("-----------------------------plugin-------------------------");
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        System.out.println("====setProperties======");
    }

}

如果项目没有使用PageHelper,该拦截器是正常能拦截,并且能实现sql修改,sql记录,抓取sql的功能

但是项目一但使用了PageHelper 该拦截器会失效
原因分析:
com.github.pagehelper.PageInterceptor#intercept
在这里插入图片描述
拦截器是责任链的形式一半结束时候会往下传递invocation.proceed();
通过分析,发现拦截器与pagehelper定义分页拦截器有冲突,分页拦截器先调用,他在调用完成后没有往下调,
所以自定义拦截器不生效

解决方案:
思路:想办法吧myInterceptor 弄到pageInterceptor的后面去。
1.让自定义的拦截器不交由spring管理,在项目启动的时候自己new一个,添加到拦截器链的最后面

/**
 * mybatis拦截器配置
 * @author alan
 */
@Configuration
public class MybatisInterceptorAutoConfiguration {

    @Autowired
    private List<SqlSessionFactory> sqlSessionFactoryList;

    /**
     * 只会执行一次
     * 顺序:Constructor(构造方法) -> @Autowired(依赖注入) -> @PostConstruct(注释的方法)
     */
    @PostConstruct
    public void addMysqlInterceptor() {
        //创建自定义mybatis拦截器,添加到chain的最后面
        ExamplePlugin mybatisInterceptor = new ExamplePlugin();
        for (SqlSessionFactory sqlSessionFactory : sqlSessionFactoryList) {
            org.apache.ibatis.session.Configuration configuration = sqlSessionFactory.getConfiguration();
            //自己添加
            configuration.addInterceptor(mybatisInterceptor);
        }
    }
}

注意
需要拦截器拦截的是同一个目标方法,chain中拦截器执行顺序才会生效
比如myInterceptor 和pageInterceptor 拦截的都是拦截Excutor的query方法,可以生效
对象执行顺序如下(先—》后) (不受拦截器在chain中顺序控制)
1.Executor
(update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
2.ParameterHandler
(getParameterObject, setParameters)
3.StatementHandler
(prepare, parameterize, batch, update, query)
4.ResultSetHandler
(handleResultSets, handleOutputParameters)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值