pageable设置size_SpringdDataJpa如何创建一个不分页,但是排序的pageable
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的调用)
@NoRepositoryBean
public interface CustomRepository {
Page findAllCustom(Pageable pageable);
Page findAllCustom(@Nullable Specification spec, Pageable pageable);
}
其次我们再写SimpleJpaRepository的定制实现,依此我们来实现刚才说的findAllCustom逻辑,实现细节就不讲了,反正就是按照需求来就可以了
public class CustomSimpleJpaRepository extends SimpleJpaRepository
implements CustomRepository {
private final EntityManager em;
public CustomSimpleJpaRepository(Class domainClass, EntityManager em) {
super(domainClass, em);
this.em = em;
}
@Override
public Page findAllCustom(Pageable pageable) {
if (isUnpaged(pageable) && isNotContainsSort(pageable)) {
return new PageImpl(findAll());
}
return findAllCustom((Specification) null, pageable);
}
@Override
public Page findAllCustom(Specification spec, Pageable pageable) {
TypedQuery query = getQueryCustom(spec, pageable);
return isUnpaged(pageable) ? new PageImpl(query.getResultList())
: readPage(query, getDomainClass(), pageable, spec);
}
protected TypedQuery getQueryCustom(@Nullable Specification spec, Pageable pageable) {
Sort sort = (pageable.isPaged() || isContainsSort(pageable))
? pageable.getSort()
: Sort.unsorted();
return getQuery(spec, getDomainClass(), sort);
}
private static boolean isNotContainsSort(Pageable pageable) {
return !isContainsSort(pageable);
}
private static boolean isContainsSort(Pageable pageable) {
return !pageable.getSort().isEmpty();
}
private static boolean isUnpaged(Pageable pageable) {
return pageable.isUnpaged();
}
}
接下来我们要模拟默认的SimpleJpaRepository是如何注入到Spring里的方式把CustomSimpleJpaRepository注入进去
默认的是通过FactoryBean的方式注入的,也就是JpaRepositoryFactoryBean,而JpaRepositoryFactoryBean其实又通过一个工厂JpaRepositoryFactory来创建了SimpleJpaRepository
因此我们也需要模拟一个JpaRepositoryFactoryBean和JpaRepositoryFactory,分别叫CustomRepositoryFactoryBean和CustomRepositoryFactory
public class CustomRepositoryFactoryBean, S, ID>
extends JpaRepositoryFactoryBean {
public CustomRepositoryFactoryBean(Class extends T> repositoryInterface) {
super(repositoryInterface);
}
protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
return new CustomRepositoryFactory(em);
}
}
public class CustomRepositoryFactory extends JpaRepositoryFactory {
private final EntityManager em;
public CustomRepositoryFactory(EntityManager em) {
super(em);
this.em = em;
}
@Override
protected JpaRepositoryImplementation, ?> getTargetRepository(
RepositoryInformation information,
EntityManager entityManager) {
return new CustomSimpleJpaRepository(information.getDomainType(), entityManager);
}
protected Class> getRepositoryBaseClass(RepositoryMetadata metadata) {
return CustomSimpleJpaRepository.class;
}
}
由于CustomRepositoryFactoryBean和CustomRepositoryFactory都是分别继承了JpaRepositoryFactoryBean和JpaRepositoryFactory,所以里面的代码不是很多,稍微改改就可以了,这里也不多说了
最后我们的UserRepository当然要继承我们新的CustomRepository就可以了
public interface UserRepository extends JpaRepository,
CustomRepository {
}
当然没忘了加上@EnableJpaRepositories来指明我们当前的repositoryFactoryBeanClass是谁
@SpringBootApplication
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class Demo2Application {
public static void main(String[] args) {
SpringApplication.run(Demo2Application.class, args);
}
}
还有我们的调用的地方就不能再使用findAll(Pageable),而是我们的
findAllCustom(Pageable)
最后执行也可以看到,是按照名字升序排列的了
以上就是答案吧,希望题主和刚评论我的小哥能理解我的心情,毕竟程序猿也不希望大家说他的代码有bug吧,但其实我一直是不怕bug,我怕需求不明确,问题不明确,这让我想看有时候都看不了。。。╮(╯▽╰)╭
虽然自己平常用的时候没有用到Pageable.unpaged()返回的这个枚举Unpaged,但是点进去看,无非是用枚举单例模式创建了一个Pageable的实例嘛
所以针对你提到的问题,从中我想回答两个疑问,当然也许不是疑问,算是理解方式
你提到 只有getSort(),没有setSort()
关于这一点,你的理解可能有点点偏差,当然编程思想很多,只要能解决问题都是好思想,不一概而论,不过这里分享哈我的理解,主要是Pageable.unpaged()本身就是Pageable接口的实例,没有setSort()方法,其实就是Pageable接口没有setSort()方法,Pageable接口本身代表着分页信息的抽象,这个抽象定义了分页信息应该有的抽象行为,这种抽象接口,在我自己的开发经验中定义为属于实体信息的抽象,不是流程类的抽象接口,实体信息的抽象我一般会更多的注意抽象实体信息本身所具有的性质或者叫属性,那是去定义从一个实体中你能有拿到什么信息,而不是注入或者修改什么信息,所以在我看来一个分页信息对象没有setSort()很正常,就像假如你把人类做一个抽象接口叫Person,Person里有个属性名字(name),你觉得你的接口Person应不应该有个setName的方法么?
如何处理这种问题(你想要不分页,但是需要排序)
处理方式其实也很简单,你都看到了别人官方怎么做了。。。你不就是学着官方改改不就完了么。。。也就是你也学着Pageable.unpaged()写一个新的枚举,其他的都仿照Pageable.unpaged(),只有getSort方法你进行你的定制修改,写一个新的枚举叫UnpagedSortById,举例如下:
public enum UnpagedSortById implements Pageable {
INSTANCE;
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#isPaged()
*/
@Override
public boolean isPaged() {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#previousOrFirst()
*/
@Override
public Pageable previousOrFirst() {
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#next()
*/
@Override
public Pageable next() {
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#hasPrevious()
*/
@Override
public boolean hasPrevious() {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getSort()
*/
@Override
public Sort getSort() {
return new Sort(Sort.Direction.DESC, "id");
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getPageSize()
*/
@Override
public int getPageSize() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getPageNumber()
*/
@Override
public int getPageNumber() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getOffset()
*/
@Override
public long getOffset() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#first()
*/
@Override
public Pageable first() {
return this;
}
}
很狠哈,注释都不带改的,直接粘贴大法搞定,其实其中getSort方法改改
当然这样是可以解决问题的,不过从我个人编码习惯来说,我觉得UnpagedSortById这个枚举不ok,因为从枚举来看只能按照id排序,如果以后还要其他字段排序,我还得写个UnpagedSortByXXX这样的枚举,里面的重复代码就多了,索性直接可以干脆大家共享一个枚举,只是区分不同的Sort即可,比如这样:
@Getter
@AllArgsConstructor
public enum UnpagedSort implements Pageable {
BY_ID_DESC(new Sort(Sort.Direction.DESC, "id")),
BY_NAME_ASC(new Sort(Sort.Direction.ASC, "name")),
;
private Sort sort;
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#isPaged()
*/
@Override
public boolean isPaged() {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#previousOrFirst()
*/
@Override
public Pageable previousOrFirst() {
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#next()
*/
@Override
public Pageable next() {
return this;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#hasPrevious()
*/
@Override
public boolean hasPrevious() {
return false;
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getPageSize()
*/
@Override
public int getPageSize() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getPageNumber()
*/
@Override
public int getPageNumber() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#getOffset()
*/
@Override
public long getOffset() {
throw new UnsupportedOperationException();
}
/*
* (non-Javadoc)
* @see org.springframework.data.domain.Pageable#first()
*/
@Override
public Pageable first() {
return this;
}
}
以上是个人看法,仅供参考哈
pageable设置size_SpringdDataJpa如何创建一个不分页,但是排序的pageable相关推荐
- [moka同学笔记转载]Yii 设置 flash消息 创建一个渐隐形式的消息框
来源:http://www.cnblogs.com/xp796/p/5481004.html Yii 设置 flash消息 创建一个渐隐形式的消息框 1 /*适用情况:比如提交一个表单,提交完成之后在 ...
- android升序降序按钮,创建一个按钮,将排序MYSQL查询升序和降序
我是一名学生编码器. 我想创建一个排序按钮,当按下时,按升序排序MYSQL查询.然后再次按下时,它将按降序排列.对,现在,它只是显示升序和降序表背靠背.创建一个按钮,将排序MYSQL查询升序和降序 形 ...
- 球体动画Android,使用CSS创建一个炫酷的球体动画效果
我最近看到了一个纯CSS实现的球体动画效果: 经过研究上面的效果实现起来大致可以分为五个步骤,下面就来一一介绍. 1.使用Jade和SCSS生成一个圆圈 创建一个圆圈的第一步是生成所有组成圆圈的粒子. ...
- 前端实现炫酷动效_web前端入门到实战:使用CSS创建一个炫酷的球体动画效果
一个纯CSS实现的球体动画效果: 经过研究上面的效果实现起来大致可以分为五个步骤,下面就来一一介绍. 1.使用Jade和SCSS生成一个圆圈 创建一个圆圈的第一步是生成所有组成圆圈的粒子.有了Jade ...
- Idea2020创建一个Servlet
前言:在创建一个web项目的基础上,创建一个Servlet.Servlet可以用来接收页面的请求并可以做出响应Idea2020 创建web项目_txj的博客-CSDN博客目录一.创建一个空项目二.创建 ...
- 为计算机创建一个新的用户,win10系统创建一个新账户的解决步骤
win10系统使用久了,好多网友反馈说关于对win10系统创建一个新账户设置的方法,在使用win10系统的过程中经常不知道如何去对win10系统创建一个新账户进行设置,有什么好的办法去设置win10系 ...
- 基于Metronic的Bootstrap开发框架经验总结(16)-- 使用插件bootstrap-table实现表格记录的查询、分页、排序等处理...
在业务系统开发中,对表格记录的查询.分页.排序等处理是非常常见的,在Web开发中,可以采用很多功能强大的插件来满足要求,且能极大的提高开发效率,本随笔介绍这个bootstrap-table是一款非常有 ...
- 创建一个ASP通用分页类(完整版)
从开始学习到使用ASP到现在也写了不少程序了,最令人头痛的是写数据分页,每次都是由于几个变量名或几个参数的不同,因而需要每次都写哪一段冗长而又繁杂的分页代码,代码长了使得程序的可读性变差,容易出差,调 ...
- Java连接HBASE数据库,创建一个表,删除一张表,修改表,输出插入,修改,数据删除,数据获取,显示表信息,过滤查询,分页查询,地理hash
准备工作 1.创建Java的Maven项目 创建好的目录结构如下: 另外注意junit的版本,最好不要太高,最开始笔者使用的junit4.12的,发现运行的时候会报错.最后把Junit的版本改成4.7 ...
最新文章
- observable_在Spring MVC流中使用rx-java Observable
- 谈谈document.ready和window.onload的区别
- php 企业号文本消息推送,Python如何实现微信企业号文本消息推送功能的示例
- Ubuntu安装PostgreSQl
- log file sync
- OpenCV4.4.0+VS2017 环境配置
- oracle like 条件拼接
- LASSOS方程--图像降噪
- YOLOv5算法详解
- WPF 实现验证码控件
- 深刻理解Servlet运行机制和生命周期
- 06MySQL基本函数的使用
- 查询出各个学科的前3名的同学信息的Sql
- 图 | 为什么存在关于图的研究
- 产品经理为什么越来越不值钱?不懂数据,只能尴尬退场
- C语言程序设计基础实验教程,C语言程序设计基础实验教程
- php dw制作购物车,php – 以编程方式向WooCommerce购物车添加免税费用
- 使用BoundsChecker检测内存泄漏
- JavaScript跨域请求
- 如果报华为网络工程师中级培训班一般学费多少?
热门文章
- 【详细】2021阿里云免费SSL证书申请
- emf是什么格式_蓝宝石:第一次尝试是基于EMF。
- Word怎么转换Markdown
- 想变身“科技型”企业?掌汇云数字化服务平台为工业升级加分
- 15.Unity2D 横版 骨骼动画 之 单张切片图骨骼动画+Aseprite像素画软件
- 周杰伦新歌发布,爬取《Mojito》MV弹幕,看看粉丝们都说的些啥!
- win10无法打开计算机上的组策略对象,Win10组策略怎么打开_Win10如何打开组策略编辑器?-192路由网...
- css3 左右晃动效果
- NPOI合并单元格后的边框设置
- RSA密码体制(头歌)