MyBatis使用—— MyBatis实现分页
一.Mybatis实现分页的介绍
1.1Mybatis实现分页的原因:
- 用户体验:在展示大量数据的情况下,将整个数据集一次性加载到页面上会导致页面加载缓慢甚至崩溃,分页可以让用户按需加载数据,提高页面响应速度,改善用户体验;
- 系统性能:分页可以减少数据库的负载,降低系统内存消耗和网络传输开销,避免对数据库和系统资源造成过大的压力;
- 数据安全性:通过分页,可以限制一次性返回的数据量,减少敏感数据被一次性泄露的机会,提高数据安全性;
- 业务需求:很多业务场景下需要对大量数据进行分页展示,比如电商网站的商品列表、新闻资讯的列表等,分页功能是满足这类需求的基本要求。
1. 2Mybatis实现分页常用的方式:
二.Mybatis具体实现实现分页
1.前提准备工作:
1.1 创建数据表
1.2 创建实体类
1.3 创建接口Dao
1.4 创建SQL映射文件
1.5 创建测试类
2、通过List结果集实现分页:
通过List结果集实现分页的原理:将需要分页处理的数据先从数据库中全部取出,然后在List结果集中截取需要的部分。
2.1 添加接口方法:
在ICourseDao接口文件中创建名为“getPageCourseByList”的方法:
public interface ICourseDao {
*//通过List结果集实现分页*
List<Course> getPageCourseByList(); }
2.2 添加SQL标签:
在CourseMapper.xml中添加select标签,具体代码如下所示:
<select id="getPageCourseByList" resultType="Course">
select * from course
</select>
2.3 添加测试方法:
在CourseTest测试类中实现为“pageByList”的分页方法:
private List<Course> pageByList(int currPage, int pageSize){
//查询全部数据
List<Course> courses = courseDao.getPageCourseByList();
//从第几条数据开始
int firstIndex = (currPage-1)*pageSize;
//到第几条结束
int lastIndex = currPage*pageSize;
//直接在List中截取
return courses.subList(firstIndex,lastIndex);
}
在CourseTest测试类中为“TestGetPageCourseByList”的测试方法测试该分页方法:
@Test
public void TestGetPageCourseByList(){
//总记录共10条。假设总共分为4页,每页最多3条记录
System.out.println("===========================第二页记录为:=====================");
List<Course> secondPage = pageByList(2,3);
for (Course course : secondPage){
System.out.println(course);
}
System.out.println("===========================第四页记录为:=====================");
List<Course> lastPage = pageByList(4,1);
for (Course course : lastPage){
System.out.println(course);
}
}
3、通过SQL参数实现分页
通过SQL参数实现分页的原理为:
通过SQL语句中的limit关键字实现分页查询;
limit关键字所需要的参数则由方法通过参数传递的方式给出;
3.1 添加接口方法
在ICourseDao接口文件中创建名为“getPageCourseBySQL”的方法,具体代码如下所示:
public interface ICourseDao {
//通过List结果集实现分页
List<Course> getPageCourseByList();
//通过SQL参数实现分页
List<Course> getPageCourseBySQL(Map<String,Object> data);
}
3.2 添加SQL标签
在CourseMapper.xml添加分页:
<mapper namespace="com.ccff.mybatis.dao.ICourseDao" >
<!--通过List结果集实现分页-->
<select id="getPageCourseByList" resultType="Course">
select * from course
</select>
<!--通过SQL参数实现分页-->
<select id="getPageCourseBySQL" parameterType="map" resultType="Course">
select * from course limit #{currIndex} , #{pageSize}
</select>
</mapper>
3.3 添加测试方法
然后在CourseTest测试类中实现名为“TestGetPageCourseBySQL”的测试方法:
@Test
public void TestGetPageCourseBySQL(){
Map<String,Object> data = new HashMap<>();
data.put("currIndex",3);
data.put("pageSize",3);
List<Course> thirdPage = courseDao.getPageCourseBySQL(data);
System.out.println("===========================第三页记录为:=====================");
for (Course course : thirdPage){
System.out.println(course);
}
}
4、通过RowBounds实现分页
MyBatis框架本身已经对分页进行了一定程度的支持,它内置了一个专门处理分页的类RowBounds:
public class RowBounds {
public static final int NO_ROW_OFFSET = 0;
public static final int NO_ROW_LIMIT = 2147483647;
public static final RowBounds DEFAULT = new RowBounds();
private int offset;
private int limit;
public RowBounds() {
this.offset = 0;
this.limit = 2147483647;
}
public RowBounds(int offset, int limit) {
this.offset = offset;
this.limit = limit;
}
public int getOffset() {
return this.offset;
}
public int getLimit() {
return this.limit;
}
}
offset属性时偏移量:即从第几行开始读取记录。limit是限制条数,默认值为0,只要给接口增加一个RowBounds参数即可。
4.1 添加接口方法:
在ICourseDao接口文件中创建名为“getPageCourseByRowBounds”的方法:
public interface ICourseDao {
//通过List结果集实现分页
List<Course> getPageCourseByList();
//通过SQL参数实现分页
List<Course> getPageCourseBySQL(Map<String,Object> data);
//通过RowBounds实现分页
List<Course> getPageCourseByRowBounds(RowBounds rowBounds);
}
4.2 添加SQL标签:
在CourseMapper.xml中添加select标签:
<mapper namespace="com.ccff.mybatis.dao.ICourseDao" >
<!--通过List结果集实现分页-->
<select id="getPageCourseByList" resultType="Course">
select * from course
</select>
<!--通过SQL参数实现分页-->
<select id="getPageCourseBySQL" parameterType="map" resultType="Course">
select * from course limit #{currIndex} , #{pageSize}
</select>
<!--通过RowBounds实现分页-->
<select id="getPageCourseByRowBounds" resultType="Course">
select * from course
</select>
</mapper>
在select标签中,RowBounds参数是MyBatis的一个附加参数,MyBatis会自动识别它。
4.3 添加测试方法:
在CourseTest测试类中创建名为“TestGetPageCourseByRowBounds”的测试方法:
@Test
public void TestGetPageCourseByRowBounds(){
RowBounds rowBounds = new RowBounds(0,3);
List<Course> firstPage = courseDao.getPageCourseByRowBounds(rowBounds);
System.out.println("===========================第一页记录为:=====================");
for (Course course : firstPage){
System.out.println(course);
}
}
@Test
public void TestGetPageCourseByRowBounds(){
RowBounds rowBounds = new RowBounds(0,3);
List<Course> firstPage = courseDao.getPageCourseByRowBounds(rowBounds);
System.out.println("===========================第一页记录为:=====================");
for (Course course : firstPage){
System.out.println(course);
}
}
5、通过插件实现分页
5.1 添加依赖jar包
需要在WEB-INF/lib下导入其依赖的两个jar包:
pagehelper-5.1.8.jar和jsqlparser-0.9.5.jar
5.2 配置分页插件
使用PageHelper插件,则需要在全局配置文件中进行配置:
<configuration>
<!--注册DB连接四要素的属性文件-->
<properties resource="jdbc.properties" />
<!--全局参数设置-->
<settings>
<!-- 配置LOG信息 -->
<setting name="logImpl" value="LOG4J" />
<!-- 延迟加载总开关 -->
<setting name="lazyLoadingEnabled" value="true"/>
<!-- 侵入式延迟加载开关 -->
<setting name="aggressiveLazyLoading" value="true"/>
<!-- 关闭二级查询缓存 -->
<!--<setting name="cacheEnabled" value="false" />-->
</settings>
<!--配置别名-->
<typeAliases>
<!--<typeAlias type="com.ccff.mybatis.model.User" alias="User"/>-->
<package name="com.ccff.mybatis.model"/>
</typeAliases>
<!--配置自定义对象工厂-->
<objectFactory type="com.ccff.mybatis.objectFactory.CartObjectFactory"/>
<!--配置分页插件-->
<plugins>
<plugin interceptor="com.github.pagehelper.PageInterceptor" />
</plugins>
<!-- 和spring整合后 environments配置将废除-->
<environments default="development">
<environment id="development">
<!-- 使用jdbc事务管理-->
<transactionManager type="JDBC" />
<!-- 数据库连接池-->
<dataSource type="POOLED">
<property name="driver" value="${jdbc.driver}"/>
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</dataSource>
</environment>
</environments>
<!--配置SQL映射文件的位置-->
<mappers>
<mapper resource="sqlmap/UserMapper.xml"/>
<mapper resource="sqlmap/StudentMapper.xml"/>
<mapper resource="sqlmap/BasketballPlayerMapper.xml"/>
<mapper resource="sqlmap/FinacialMapper.xml"/>
<mapper resource="sqlmap/NewsLabelMapper.xml" />
<mapper resource="sqlmap/LazyLoadingMapper.xml" />
<mapper resource="sqlmap/BookMapper.xml" />
<mapper resource="sqlmap/GoodsMapper.xml" />
<mapper resource="sqlmap/GamePlayerMapper.xml" />
<mapper resource="sqlmap/CourseMapper.xml" />
</mappers>
</configuration>
5.3 添加接口方法
在ICourseDao接口文件中创建名为“getPageCorseByPagePlugin”的方法:
public interface ICourseDao {
//通过List结果集实现分页
List<Course> getPageCourseByList();
//通过SQL参数实现分页
List<Course> getPageCourseBySQL(Map<String,Object> data);
//通过RowBounds实现分页
List<Course> getPageCourseByRowBounds(RowBounds rowBounds);
//通过分页插件实现分页
List<Course> getPageCorseByPagePlugin();
}
5.4 添加SQL标签
在CourseMapper.xml中添加select标签、:
<mapper namespace="com.ccff.mybatis.dao.ICourseDao" >
<!--通过List结果集实现分页-->
<select id="getPageCourseByList" resultType="Course">
select * from course
</select>
<!--通过SQL参数实现分页-->
<select id="getPageCourseBySQL" parameterType="map" resultType="Course">
select * from course limit #{currIndex} , #{pageSize}
</select>
<!--通过RowBounds实现分页-->
<select id="getPageCourseByRowBounds" resultType="Course">
select * from course
</select>
<!--通过分页插件实现分页-->
<select id="getPageCorseByPagePlugin" resultType="Course">
select * from course
</select></mapper>
5.5 添加测试方法
然后在CourseTest测试类中创建名为“TestGetPageCorseByPagePlugin”的测试方法:
@Test
public void TestGetPageCorseByPagePlugin(){
PageHelper.startPage(4,3);
List<Course> ForthPage = courseDao.getPageCorseByPagePlugin();
System.out.println("===========================第四页记录为:=====================");
for (Course course : ForthPage){
System.out.println(course);
}
}
三.总结
1. 4种方法比较:
1.1SQL语句:
- 优点:使用数据库原生的分页语法,简单直接,适用于支持LIMIT和OFFSET的数据库。
- 缺点:需要手动拼接分页语句,不够灵活;在处理大数据量时,随着偏移量的增加,性能可能下降。
1.2插件(如MyBatis-PageHelper):
- 优点:功能丰富,提供了更多的分页控制选项,如排序、总记录数统计等;配置简单,通过插件自动拦截并实现分页逻辑。
- 缺点:引入额外依赖,需要在项目中添加相应的插件;可能会受插件版本兼容性的限制。
1.3RowBounds类:
- 优点:MyBatis内置的方式,无需额外依赖,可通过参数直接传递分页信息,易于使用。
- 缺点:需要在每个查询方法中手动传递RowBounds对象,不够灵活;对于复杂查询需求,可能需要自己计算偏移量和限制数量。
1.4List集合:
- 优点:使用Java集合类来接收查询结果,灵活方便,可以自由操作结果集。
- 缺点:需要手动处理分页逻辑,包括计算偏移量、限制数量,可能会增加开发复杂度。