SpringdDataJpa如何创建一个不分页,但是排序的pageable
public Pageable createPagenation() {
int page = WebClass.requestToInt("pageNo");
int pageSize = WebClass.requestToInt("pageSize");
Sort s = new Sort(Sort.Direction.DESC, "id");
if (page > 0 && pageSize > 0) {
return PageRequest.of(page - 1, pageSize, s);
} else {
return Pageable.unpaged();
}
}
想封装一个自动构建分页对象的方法,
但是,在不需要分页的时候,
用Pageable.unpaged()
返回不需要分页的对象,但是这个对象,无法设置排序属性,
只有getSort(),没有setSort()。
请问有大佬知道应该怎么处理吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
2020-07-16 更新一波
今天看到有个小哥在这个里面评论说他也报错了,报了
UnsupportedOperationException
这跟之前题主说的报错也是差不多,就是我的方案总之会报错
但是当时我也给题主回复了,我说能不能把报错提出来让我看看,既然大家讨论,也不能就说报错就完事了吧,好歹我也得看到堆栈啥的才好说噻,而且当时我记得很清楚我也去试了我的方案是没有报错了,所以我当时就回复希望题主贴出点东西供我参考一下
当然后面题主也没有提,虽然我当时还等着题主给后续的堆栈或者其他信息呢,一直没有,这样就不了了之了,直到今天再有人说有报错,但是还是没有给其他信息,我是气不打一处来,我不质疑别人给我的答案说有问题,但是好歹得有点东西提供给我吧。。。这让我都怀疑我当时到底测试过没有了
于是我今天再开了一个demo,试了一下我的,确实没有报错
可以正常返回
我再仔细看了一下当时题主的描述说的词语
看就是说某个判断之后,去调用了
getPageSize
方法导致报错,debug
了一下,感觉应该是这些个地方也就是
Pageable
的isPaged()
方法,由于没有其他的堆栈和任何信息,我只能这么猜。但是其实我给的方案中,由于我们自己实现了
Pageable
,所以明显这里是false
的(别说是我这次改的哈,大家可以看我的答案编辑记录,之前提交的一次之后再也没有改过,除了现在正在编辑的,第一版我就是返回的false
)所以我只能猜测题主或者今天评论我这个会抛错的,估计是因为
isPaged()
返回的是true
确实,我试了一下,如果这里改成了返回
true
,一定会报错虽然这样之后可以证明我之前的方案起来来说不会报错,但是这个时候我在刚才读源码的过程中却发现我这个方案是有个 致命 问题的,最开始我尽然没发现
其实也是可以发现,如果题主完全按照我的代码
copy
过去一定会发现的,因为copy
过去的代码确实不会报错,但是,这个方案却不会排序了,原因在这进入
findAll()
方法后,调用getQuery
的参数中,直接采用的Sort.unsorted()
了,也就是没有顺序了那这样就失去意义了嘛,这样反而我自己证明我方案有问题的,于是我再走读了一下代码,从刚才最后
getQuery
入手,我们可以看到,其实getQuery
方法是可以支持传不是unsorted()
的Sort
的,所以我之前的思路上,其实应该是可行,只是不能直接简单用了一个实现了Pageable
的枚举来做,还不够,因为原因出在findAll()
的实现类上,也就是默认实现SimpleJpaRepository
上,这是我们平常写的repository
的默认实现,我们只写接口不写实现,就是因为这个类所以思路就简单了,我们要提供定制化的
SimpleJpaRepository
所以我找了一下怎么定制化这个,也很简单(当然比之前只是写枚举要复杂点)
首先我们以示区分之前的
findAll(Pageable pageable)
方法,也就是要区分之前默认的接口PagingAndSortingRepository
我们自定义一个接口
CustomRepository
,里面一个方法findAllCustom
。参数也只有一个Pageable
,但是作用应该是如果是不分页,但是有传入sort
,则要按照sort
进行排序,如果要分页,则按照传统分页操作来(当然为了以后扩展,我这里再加了一个增加查询条件
Specification
的分页查询方法,其实第一个方法就是Specification
为null
的调用)其次我们再写
SimpleJpaRepository
的定制实现,依此我们来实现刚才说的findAllCustom
逻辑,实现细节就不讲了,反正就是按照需求来就可以了接下来我们要模拟默认的
SimpleJpaRepository
是如何注入到Spring
里的方式把CustomSimpleJpaRepository
注入进去默认的是通过
FactoryBean
的方式注入的,也就是JpaRepositoryFactoryBean
,而JpaRepositoryFactoryBean
其实又通过一个工厂JpaRepositoryFactory
来创建了SimpleJpaRepository
因此我们也需要模拟一个
JpaRepositoryFactoryBean
和JpaRepositoryFactory
,分别叫CustomRepositoryFactoryBean
和CustomRepositoryFactory
由于
CustomRepositoryFactoryBean
和CustomRepositoryFactory
都是分别继承了JpaRepositoryFactoryBean
和JpaRepositoryFactory
,所以里面的代码不是很多,稍微改改就可以了,这里也不多说了最后我们的
UserRepository
当然要继承我们新的CustomRepository
就可以了当然没忘了加上
@EnableJpaRepositories
来指明我们当前的repositoryFactoryBeanClass
是谁还有我们的调用的地方就不能再使用
findAll(Pageable)
,而是我们的findAllCustom(Pageable)
最后执行也可以看到,是按照名字升序排列的了
以上就是答案吧,希望题主和刚评论我的小哥能理解我的心情,毕竟程序猿也不希望大家说他的代码有
bug
吧,但其实我一直是不怕bug
,我怕需求不明确,问题不明确,这让我想看有时候都看不了。。。╮(╯▽╰)╭虽然自己平常用的时候没有用到
Pageable.unpaged()
返回的这个枚举Unpaged
,但是点进去看,无非是用枚举单例模式创建了一个Pageable
的实例嘛所以针对你提到的问题,从中我想回答两个疑问,当然也许不是疑问,算是理解方式
关于这一点,你的理解可能有点点偏差,当然编程思想很多,只要能解决问题都是好思想,不一概而论,不过这里分享哈我的理解,主要是
Pageable.unpaged()
本身就是Pageable
接口的实例,没有setSort()
方法,其实就是Pageable
接口没有setSort()
方法,Pageable
接口本身代表着分页信息的抽象,这个抽象定义了分页信息应该有的抽象行为,这种抽象接口,在我自己的开发经验中定义为属于实体信息的抽象,不是流程类的抽象接口,实体信息的抽象我一般会更多的注意抽象实体信息本身所具有的性质或者叫属性,那是去定义从一个实体中你能有拿到什么信息,而不是注入或者修改什么信息,所以在我看来一个分页信息对象没有setSort()
很正常,就像假如你把人类做一个抽象接口叫Person
,Person
里有个属性名字(name
),你觉得你的接口Person
应不应该有个setName
的方法么?处理方式其实也很简单,你都看到了别人官方怎么做了。。。你不就是学着官方改改不就完了么。。。也就是你也学着
Pageable.unpaged()
写一个新的枚举,其他的都仿照Pageable.unpaged()
,只有getSort
方法你进行你的定制修改,写一个新的枚举叫UnpagedSortById
,举例如下:很狠哈,注释都不带改的,直接粘贴大法搞定,其实其中
getSort
方法改改当然这样是可以解决问题的,不过从我个人编码习惯来说,我觉得
UnpagedSortById
这个枚举不ok,因为从枚举来看只能按照id排序,如果以后还要其他字段排序,我还得写个UnpagedSortByXXX
这样的枚举,里面的重复代码就多了,索性直接可以干脆大家共享一个枚举,只是区分不同的Sort
即可,比如这样:以上是个人看法,仅供参考哈
觉得需求有问题,不想分页,把pageSize搞大不就可以了么?比如说10000, 至少还有个保险,真的数据几十万也至于死掉。