用JPA分页查询报错说:查询中至少提供了两个参数,但只有一个参数

发布于 2022-09-11 19:32:00 字数 1067 浏览 18 评论 0

    @GetMapping("/getByMaterialCode")
    List<PrimaryMaterialMain> getByMaterialCode(PrimaryMaterialMain materialCode) {
        PageRequest pageable = PageRequestUtil.buildPageRequest(0, 7, "");
        return primaryMaterialMainService.getByMaterialCode(materialCode, pageable).getContent();
    }

service:

public Page<PrimaryMaterialMain> getByMaterialCode(PrimaryMaterialMain materialCode, PageRequest pageable) {
        Specification<PrimaryMaterialMain> specification = SpecificationBuilder.buildSpecification(materialCode);
        Page<PrimaryMaterialMain> lists = primaryMaterialMainRepository.findAllByMaterialCodeContaining(specification, pageable);
        return lists;
    }

Dao:

Page<PrimaryMaterialMain> findByMaterialCodeContaining(Specification<PrimaryMaterialMain> specification, 
             PageRequest pageable);

然后就是报错:

clipboard.png

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

过度放纵 2022-09-18 19:32:00

题主,你好
emmm,首先小小的说哈不满,哈哈哈哈,其实就是看问题好歹也给个堆栈啊,这个就一个错误描述,精准度不够,所以我不敢保证我的方法管用,算是程序猿的一点直觉吧,下面是我个人看法的思路

如果不想看我自己的猜测过程,可以直接拉倒最下面看我的猜测,希望能帮到你,嘿嘿

整了个Spring-data-jpa的工程,从题主唯一给的错误描述出发(好吧,还是个截图。。。我得自己打出来),

At least 2 parameter(s) provided but only 1...

我首先认为这个错误应该不是题主自己抛出来的,所以直接在工程里搜索除了参数以外较完整的句子,就用这个了

parameter(s) provided but only

搜索,还真找个类,QueryParameterSetterFactory

clipboard.png

不过有两个地方,所以分别在两个地方打断点,自己创建了一个类似题主的例子,然后让其查询报错,最后发现是下面这个地方报错的

clipboard.png

可以看到,就是一个简单的断言,条件是parameterIndex < expressions.size(),从最后报错描述来对比看, expressions.size()显然是1,也就是这个Spring-data-jpa解析你提供的findByMaterialCodeContaining只需要一个查询条件的,但是奈何,题主给了两个条件,但是题主肯定说,第二个条件是分页条件PageRequest应该不算的啊,但是看起来是算上的了,所以继续沿着程序认为错误但是我们不认为错误的路径反向debug找,而且怀疑对象着重在PageRequest,当然就是要找为啥parameterIndex的大小是1的(debug看出来的),它是怎么生成的,从代码binding.getRequiredPosition()进入,最后发现它是取的类ParameterBinding的属性position,也就是说其实position此时值为2

static class ParameterBinding {

        private final @Nullable String name;
        private final @Nullable String expression;
        private final @Nullable Integer position;

那这个属性被赋值的地方只有一个,就是构造方法,并且是直接赋值的

clipboard.png

所以构造方法入口打断点,重新跑一次查询,不过这个断点加一个条件,因为我们不知道重新跑一边时,这个方法要执行几次,但是从最后条件出错的断言来看,position值是2,所以这个断点再加一个条件,防止其他的可能

clipboard.png

再跑一次之后,我们停下来了,这里是在初始化ParameterBinding并放入一个集合中,外面有一个JpaParameters的循环,从debug框中看到当前的循环的值parameterPageRequest,这个可是我们的怀疑对象

clipboard.png

加上,在是否初始化ParameterBinding之前还有个判断条件parameter.isBindable()

for (JpaParameter parameter : parameters) {

    if (parameter.isBindable()) {
        result.add(new ParameterBinding(++bindableParameterIndex));
    }
}

所以我们有理由怀疑,正因为这个判断条件通过了,导致了此时ParameterBinding生成,导致最终position值是2,所以我们在走进这个方法parameter.isBindable()去看看

@Override
public boolean isBindable() {
    return super.isBindable() || isTemporalParameter();
}

有两个判断方法,||连接,我们先看super.isBindable(),还是调用的另外的方法isSpecialParameter(),不过从方法的注释上看,貌似是我们要找的意思

/**
     * Returns whether the {@link Parameter} is to be bound to a query.
     *
     * @return
     */
public boolean isBindable() {
    return !isSpecialParameter();
}

再走入isSpecialParameter(),这个方法注释也说得很清楚了,special parameter特殊参数,感觉是那么回事了

/**
     * Returns whether the parameter is a special parameter.
     *
     * @return
     * @see #TYPES
     */
    public boolean isSpecialParameter() {
        return isDynamicProjectionParameter || TYPES.contains(parameter.getParameterType());
    }

第一个是isDynamicProjectionParameter是个booleandebug可以看到是false
第二个TYPES.contains(parameter.getParameterType()),我们看看TYPES

static final List<Class<?>> TYPES = Arrays.asList(Pageable.class, Sort.class);

emmm。。。貌似。。。有点明白了。。。当前你用的是PageRequest,不是Pageable,虽然PageRequest也是实现了Pageable接口,但是这里就是这么写了。。。也就是说方法里应该写Pageable作为方法参数,而不是实现类PageRequest

好吧。。。问题解决,顺便我也学一手(不过题主可能你还是没有解决问题,但是这是我能找到的大概问题所在吧。。。起码我改了之后,我这里的demo就可以了)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文