Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

boundSqlInterceptors初始化拦截链参数问题咨询 #587

Closed
1 task
lingaoju opened this issue Jan 18, 2021 · 3 comments
Closed
1 task

boundSqlInterceptors初始化拦截链参数问题咨询 #587

lingaoju opened this issue Jan 18, 2021 · 3 comments
Labels

Comments

@lingaoju
Copy link

  • 我已在 issues 搜索类似问题,并且不存在相同的问题.

使用环境

  • PageHelper 版本: 5.2.0
  • 数据库类型和版本: mysql8.0

功能建议

PageInterceptor中配置boundSqlInterceptors参数,设置自定义的BoundSqlInterceptor,进行拦截,修改前置修改SQL然后在进行分页,但是这个配置只会进行一次调用,debug发现是调用完这个链之后不会初始化 index,如下图
image

详细说明,尽可能提供(伪)代码示例。

期望的结果:

期望按理来说每次sql都应该走一遍这个拦截器链,现在用boundSqlInterceptors配置的默认的拦截器链不会重新进入该链方法

@lingaoju
Copy link
Author

@OverRide
public BoundSql doBoundSql(BoundSqlInterceptor.Type type, BoundSql boundSql, CacheKey cacheKey) {
if (this.interceptors == null || this.interceptors.size() == this.index) {
return this.original != null ? this.original.doBoundSql(type, boundSql, cacheKey) : boundSql;
} else {
return this.interceptors.get(this.index++).boundSql(type, boundSql, cacheKey, this);
}
}
图片不知道是否上传成功,这边用代码解释以下,这个是BoundSqlInterceptorChain类部分代码, 这里的this.index++调用后在代码中没有重置,导致不会在进入这个拦截链

@a83313886
Copy link

我也发现这个问题了。原因在于BoundSqlInterceptorChainindex字段使用,而PageHelper调用时直接复用了同一个实例,一方面在多线程场景下存在并发问题,另一方面就如 @lingaoju 所说的-计数器没有重置。

PageHelper使用同一个实例的代码如下:

    @Override
    public BoundSql doBoundSql(BoundSqlInterceptor.Type type, BoundSql boundSql, CacheKey cacheKey) {
           // ...
            BoundSqlInterceptor.Chain defaultChain = pageBoundSqlInterceptors != null ? pageBoundSqlInterceptors.getChain() : null;
            if (boundSqlInterceptor != null) {
                chain = new BoundSqlInterceptorChain(defaultChain, Arrays.asList(boundSqlInterceptor));
            } else if (defaultChain != null) {
                chain = defaultChain;
            }
            // ...
        return chain.doBoundSql(type, boundSql, cacheKey);
    }

@abel533 abel533 added the bug label Jun 6, 2021
@abel533 abel533 pinned this issue Jun 6, 2021
@abel533
Copy link
Collaborator

abel533 commented Jun 6, 2021

这是个BUG,现在的修改方式是把chain当成了模板,执行的时候初始化一个实例来解决这个问题,大家可以看看代码,测试看看有没有问题:

package com.github.pagehelper;

import org.apache.ibatis.cache.CacheKey;
import org.apache.ibatis.mapping.BoundSql;

import java.util.List;

public class BoundSqlInterceptorChain implements BoundSqlInterceptor.Chain {
    private final BoundSqlInterceptor.Chain original;
    private final List<BoundSqlInterceptor> interceptors;

    private int     index = 0;
    private boolean executable;

    public BoundSqlInterceptorChain(BoundSqlInterceptor.Chain original, List<BoundSqlInterceptor> interceptors) {
        this(original, interceptors, false);
    }

    private BoundSqlInterceptorChain(BoundSqlInterceptor.Chain original, List<BoundSqlInterceptor> interceptors, boolean executable) {
        this.original = original;
        this.interceptors = interceptors;
        this.executable = executable;
    }

    @Override
    public BoundSql doBoundSql(BoundSqlInterceptor.Type type, BoundSql boundSql, CacheKey cacheKey) {
        if(executable) {
            return _doBoundSql(type, boundSql, cacheKey);
        } else {
            return new BoundSqlInterceptorChain(original, interceptors, true).doBoundSql(type, boundSql, cacheKey);
        }
    }

    private BoundSql _doBoundSql(BoundSqlInterceptor.Type type, BoundSql boundSql, CacheKey cacheKey) {
        if (this.interceptors == null || this.interceptors.size() == this.index) {
            return this.original != null ? this.original.doBoundSql(type, boundSql, cacheKey) : boundSql;
        } else {
            return this.interceptors.get(this.index++).boundSql(type, boundSql, cacheKey, this);
        }
    }

}

@abel533 abel533 closed this as completed in 43cf9d1 Jun 6, 2021
@abel533 abel533 unpinned this issue Sep 29, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants