MyBatis中的RowBounds

article/2025/10/4 0:02:04

如何分页查询
Mybatis如何分页查询?Mysql中可以使用limit语句,但limit并不是标准SQL中的,如果是其它的数据库,则需要使用其它语句。MyBatis提供了RowBounds类,用于实现分页查询。RowBounds中有两个数字,offset和limit。

MyBatis如何利用RowBounds实现通用分页
在查询数据库时,如果没有limit语句,则ResultSet中会包含所有满足条件的数据,

RowBounds在处理分页时,只是简单的把offset之前的数据都skip掉,超过limit之后的数据不取出,上图中的代码取自MyBatis中的DefaultResultSetHandler类。跳过offset之前的数据是由方法skipRows处理,判断数据是否超过了limit则是由shouldProcessMoreRows方法进行判断。简单点说道,就是先把数据全部查询到ResultSet,然后从ResultSet中取出offset和limit之间的数据,这就实现了分页查询。

从两种场景下说明RowBounds的使用。

    SqlSession,使用SqlSession时,selectList有一个重载的方法,带有RowBounds参数,这种情况下,DAO层的实现了,可以对外界隐藏RowBounds类。如下图,Page是自定义的一个接口,用于表示分页信息,不直接使用RowBounds源于自己的一个习惯,不喜欢在Service层中侵入持久层所使用的持久化技术的类或接口。如果在Service中使用了RowBounds,Service与MyBatis就耦合了,当然,如果不要求这一点,直接要Service里写RowBounds对象也是可以的。

    1.映射接口,MyBatis提供了映射接口的形式,这种情况下,可以不写DAO接口的实现即可完成DAO层,这种情况下,DAO接口写成List<User> vip(RowBounds page),这种情况下,mybatis会完成分页查询。

回到Page接口,如果类与接口之间的关系如右类图,DAO中的方法还是vip(Page page),而调用的时候,工厂返回了一个MyBatisPage类的对象给DAO,因为MyBatisPage类继承自RowBounds类,所以此时传给DAO的Page对象也是一个RowBounds类的对象,但这种情况下却不会有分页查询的效果。

MyBatisPage类相当于一个适配器,用于适配Page接口与RowBounds,但为何给DAO一个RowBounds对象时,却没有实现分页效果,原因是MyBatis判断方法的参数中有没有RowBounds参数是在产生接口的代理时,而不是在方法调用的时候。根据DefaultSqlSession类的getMapper方法可以很快找到MapperProxyFactory类,此类的作用就是创建接口的动态代理,所以方法的调用逻辑应该要看代理的InvocationHandler对象,它是MapperProxy类,这里的处理调用比较深,在MapperProxy类中可以发现,每一个DAO接口上的方法都会对应一个MapperMethod类的对象,MapperMethod类中有一个内部类MethodSignature,这是关键的地方,每一个MapperMethod对象都依赖于一个MethodSignature对象,看看此类的构造器:

rowBoundsIndex,这个属性是用于记录MapperMthod对应的方法的参数中,RowBounds是第几个参数,getUniqueParamIndex方法的实现中,如果发现没有Rowbounds参数,则返回null,由此可见,如果DAO的方法签名为vip(Page page),则rowBoundsIndex为null,所以在调用的时候,即使Page接口的实例也是一个RowBounds的实例,也不会有分页效果。

    如果想要解决这个限制,付出的代价有点大。与Spring框架不同的是,Spring中,类与类之间依赖的是接口而不是具体类。而MyBatis从DefaultSqlSesison到MethodProx,全部依赖的是具体类,这些类没有接口,如果要想解决这个限制,需要子类化DefaultSqlSession,Configuration,MapperRegistry,MapperProxyFactory,MapperProxy,MapperMethod和MethodSignature,这些类都没有实现某个可扩展的接口,甚至没有实现接口,全部是依赖具体的类,无法从其中某个点进行扩展。至于MapperProxyFactory,它无法替换成其它工厂类,它仅仅只是隐藏了接口的代理的创建方式。

RowBounds没有覆盖equals和hashCode方法


    如果RowBounds在Service中直接new了,则在测试Service时,在mock时使用了when这样的方法,如:when(userDao.vip(rowBounds)).xxx,那么就会发生错误,因为在Service中也会new一个RowBounds,即使Service中new的那个RowBounds和单元测试中的RowBoumds的offset和limit两个数都一样,rowBounds.equals(row)也不会返回true,当然,可以使用when(userDao.vip(anyObject()))。

如何解决这个问题?有两种方式,一种是RowBounds作为参数传入Service,另一种是使用适配器,这个适配器很简单,写个RowBounds的子类,在子类中覆盖hashCode&equals方法,在Service中使用新的类。
 


http://chatgpt.dhexx.cn/article/I6uRbTeX.shtml

相关文章

row_number() over(partition by)整理

row_number() over(partition by)&#xff0c;作为oracle常用的分析函数&#xff0c;身为数据开发时必须要掌握的。不过一段时间不用&#xff0c;难免会有些忘记&#xff0c;今天整理一下一些场景下的用法。 现有表&#xff08;test_rownumber&#xff09;有如下数据&#xff…

Mybatis分页之RowBounds

Mybatis可以使用RowBounds进行分页 dao层 sql的xml文件&#xff0c;因为是java层面的分页&#xff0c;所以sql不需要分页 单元测试 因为参数是第几个开始&#xff0c;这样很不友好&#xff0c;我们一般情况分页是第几页开始&#xff0c;页大小是多少&#xff0c;所以这就需要我…

MySQL–ROW_NUMBER

MySQL–ROW_NUMBER 一、窗口函数 ​ 要讲row_number&#xff0c;首先得讲一下窗口函数。窗口函数&#xff0c;也叫OLAP函数&#xff08;Online Anallytical Processing&#xff0c;联机分析处理&#xff09;&#xff0c;可以对数据库数据进行实时分析处理。 ​ 窗口函数的基…

row_number() OVER(PARTITION BY)函数介绍

OVER(PARTITION BY)函数介绍 开窗函数 Oracle从8.1.6开始提供分析函数&#xff0c;分析函数用于计算基于组的某种聚合值&#xff0c;它和聚合函数的不同之处是&#xff1a;对于每个组返回多行&#xff0c;而聚合函数对于每个组只返回一行。 开窗函数指定了分析函…

巧用ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING

背景 数据如上&#xff0c;按id和ssny分组&#xff0c;求最大的开票时间&#xff0c;若为空&#xff0c;取非空的上一期组内最大开票时间 解 SELECT id, ssny, kpsj, max(kpsj) OVER(PARTITION BY id ORDER BY ssny desc ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) …

mybatis RowBounds 分页

在 mybatis 中&#xff0c;使用 RowBounds 进行分页&#xff0c;非常方便&#xff0c;不需要在 sql 语句中写 limit&#xff0c;即可完成分页功能。但是由于它是在 sql 查询出所有结果的基础上截取数据的&#xff0c;所以在数据量大的sql中并不适用&#xff0c;它更适合在返回数…

RowBounds分页

不再使用SQL实现分页 1.接口 //分页List<User> getUserByRowBounds(); 2.mapper.xml <!-- 分页--><select id"getUserByRowBounds" resultType"UserMap">select * from mybatis.user</select> 3.测试 Testpublic void getUserByRo…

row_number() OVER(PARTITION BY)

日萌社 人工智能AI&#xff1a;Keras PyTorch MXNet TensorFlow PaddlePaddle 深度学习实战&#xff08;不定时更新&#xff09; row_number()排序函数 统计每个部门薪资最高的员工信息&#xff08;同一个部门的员工按照薪资进行降序排序&#xff09;第一种写法&#xff1a;ro…

在VS中安装nuget离线包nupkg文件

1、打开或者新建任意一个项目 2、项目-管理NuGet程序包 3、设置 4、设置好以后如下图&#xff0c;点击确定 5、安装

Uipath打包流程为.nupkg文件

先断开oc 在publish流程&#xff0c;其中main是入口 点击publish 然后打开Uipath robot&#xff0c;可以看到流程已经同步上去了

如何将nupkg离线安装包安装到VS2017、9

不知道为什么&#xff0c;用vs自带的nuget程序管理器安装nuget包非常慢&#xff0c;而且很容易出错&#xff0c;最重要的是编译的时候能急死人&#xff0c;于是换网、自己架nuget服务器...一顿折腾。 不再废话&#xff0c;直接上干货&#xff1a; 1、在官网https://www.nuget…

VS如何安装.nupkg文件

nupkg是visual studio 的NuGet Package的一个包文件 安装nupkg包前&#xff0c;在visual studio的NuGet中会显示该包需要的.net framework runetime版本需要 还有版权归属等信息 具体看一下截图 大家可以去下载一个&#xff1a;Google Protocol buffers 3.5.1的nupkg来试试 下…

vs2010 添加nupkg文件

起因呢是这样的&#xff1a;以前一直用破解版的Teechartd&#xff0c;其实这个问题也不大&#xff0c;也挺好的&#xff0c;只是因为它是破解的嘛&#xff1b; 近期对知识产权这块也非常重视&#xff0c;所以在这个开发中就考虑到我们未来远大的梦想&#xff0c;我们是仪表行业…

c#使用nuget.exe CLI发布 nupkg 包

2019独角兽企业重金招聘Python工程师标准>>> 准备 工具&#xff1a;nuget.exe CLI&#xff08;本人使用版本&#xff1a; NuGet Version: 4.6.2.5055&#xff09;将下载的的nuget.exe路径添加到系统变量PATH中vs创建的类库项目 操作 让项目自动生成版本号&#xff0…

如何将nupkg文件安装到VS2017

本文为原创文章、源代码为原创代码&#xff0c;如转载/复制&#xff0c;请在网页/代码处明显位置标明原文名称、作者及网址&#xff0c;谢谢&#xff01; 开发工具&#xff1a;VS2017 系统&#xff1a;Win10 X64 一、首先在https://www.nuget.org/下载离线nupkg文件&#xff0c…

制作NUGET包制作nupkg包

下载制作NUGET包工具 NUGETPACKAGEEXPLORER 直接下载NuGet Package Explorer软件&#xff0c;网盘CSDN等上面有好多 然后运行里面的 根据你自己的lib版本选择相应的选项 选择你的lib文件 选择Edit进行基础信息编辑 填写基础信息&#xff0c;图标填写绝对磁盘地址即可&#xf…

Nuget包管理器将nupkg文件导入ASP.NET MVC5项目

备注&#xff1a;使用的是Visual Stual2013。 1、新建ASP.NET Web应用程序&#xff0c;自定义项目名、解决方案名 2、选择对应的模板&#xff0c;可以勾选添加单元测试 3、选择菜单栏&#xff1a;工具——Nuget包管理器——程序包管理器设置(N)&#xff0c; 出现界面如下&…

没有外网只有内网,nuget离线安装nupkg的方法

2018.11.24更新&#xff1a;终极解决方案&#xff0c;去内网搭一个私有库把 目录 1. 在有外网的电脑上先安装成功&#xff0c;然后拷到没有外网的电脑上。2. 创建Vue模板成功&#xff0c;但是运行dotnet restore找不到资源3. 按照指定路径找资源&#xff0c;而不是让它自动的去…

PowerShell Gallery .nupkg手动下载将.nupkg文件重命名为.zip,然后将内容提取到本地文件夹中

PowerShell Gallery支持直接从网站下载软件包&#xff0c;而无需使用PowerShellGet cmdlet。您可以将任何软件包下载为NuGet软件包&#xff08;.nupkg&#xff09;文件&#xff0c;然后将其复制到内部存储库中。 注意 手册包下载是不打算作为一个替代Install-Module小命令。下载…

C#安装本地nupkg包

联机库 搜索nuGet 下载安装 工具菜单中多了一个nuGet选项 扩展管理器中也可以看到 打开一个项目 什么都没有 添加一个 打开“工具”——“选项” 点击绿色的加号&#xff0c;源为自己下载的包所在的文件夹路径&#xff0c;名称自己起 点击确定 可以安装 很快就安装好了&#x…