MyBatis使用篇(十一)—— MyBatis实现分页

16 篇文章 0 订阅
14 篇文章 0 订阅

1、搭建演示环境

1.1 创建数据表

  在mybatis数据库中创建名为“course”的数据表,并在数据表中添加测试数据。建表与插入测试语句的代码如下所示:

SET FOREIGN_KEY_CHECKS=0;

-- ----------------------------
-- Table structure for `course`
-- ----------------------------
DROP TABLE IF EXISTS `course`;
CREATE TABLE `course` (
  `id` int(255) NOT NULL auto_increment,
  `no` varchar(255) default NULL,
  `name` varchar(255) default NULL,
  `score` int(255) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of course
-- ----------------------------
INSERT INTO `course` VALUES ('1', 'C001', '数据结构', '3');
INSERT INTO `course` VALUES ('2', 'C002', '操作系统', '3');
INSERT INTO `course` VALUES ('3', 'C003', '计算机网络', '3');
INSERT INTO `course` VALUES ('4', 'C004', '计算机组成原理', '3');
INSERT INTO `course` VALUES ('5', 'C005', '算法设计与分析', '3');
INSERT INTO `course` VALUES ('6', 'C006', 'C语言程序设计', '3');
INSERT INTO `course` VALUES ('7', 'C007', '数据挖掘', '2');
INSERT INTO `course` VALUES ('8', 'C008', '机器学习', '2');
INSERT INTO `course` VALUES ('9', 'C009', 'Linus操作系统', '2');
INSERT INTO `course` VALUES ('10', 'C010', 'Java程序语言设计', '2');

  创建完毕后的数据表如下所示:
在这里插入图片描述

1.2 创建实体类

  在com.ccff.mybatis.model包下创建名为“Course”的实体类,并为成员变量提供get和set方法以及toString方法,具体代码如下:

package com.ccff.mybatis.model;

public class Course {
    private int id;
    private String no;
    private String name;
    private int score;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Course{" +
                "id=" + id +
                ", no='" + no + '\'' +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

1.3 创建接口Dao

  在com.ccff.mybatis.dao包下创建名为“ICourseDao”的空的接口Dao文件,具体代码如下所示:

package com.ccff.mybatis.dao;

public interface ICourseDao {
}

1.4 创建SQL映射文件

  在config/sqlmap文件夹下创建名为“CourseMapper.xml”的空的SQL映射文件,具体代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ccff.mybatis.dao.ICourseDao" >
</mapper>

  创建SQL映射文件完毕后,将该SQL映射文件配置到全局配置文件中的mapper加载路径中,具体配置如下:

<!--配置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>

1.5 创建测试类

  在com.ccff.mybatis.test包下创建名为“CourseTest”的测试类,具体代码如下:

package com.ccff.mybatis.test;

import com.ccff.mybatis.dao.ICourseDao;
import com.ccff.mybatis.datasource.DataConnection;
import org.apache.ibatis.session.SqlSession;
import org.junit.After;
import org.junit.Before;

import java.io.IOException;

public class CourseTest {
    private SqlSession sqlSession;
    private ICourseDao courseDao;

    @Before
    public void init() {
        DataConnection dataConnection = new DataConnection();
        try {
            sqlSession = dataConnection.getSqlSession();
            courseDao = sqlSession.getMapper(ICourseDao.class);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @After
    public void tearDown(){
        if (sqlSession != null)
            sqlSession.close();
    }
}

2、通过List结果集实现分页

  通过List结果集实现分页的原理是:将需要分页处理的数据先从数据库中全部取出,然后在List结果集中截取需要的部分。

2.1 添加接口方法

  在ICourseDao接口文件中创建名为“getPageCourseByList”的方法,具体代码如下所示:

package com.ccff.mybatis.dao;

import com.ccff.mybatis.model.Course;

import java.util.List;

public interface ICourseDao {
    //通过List结果集实现分页
    List<Course> getPageCourseByList();
}

2.2 添加SQL标签

  在CourseMapper.xml中添加select标签,具体代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ccff.mybatis.dao.ICourseDao" >
    <!--通过List结果集实现分页-->
    <select id="getPageCourseByList" resultType="Course">
        select * from course
    </select>
</mapper>

2.3 添加测试方法

  在CourseTest测试类中首先创建名为“pageByList”的分页方法,具体代码如下所示:

/**	
 * @param currPage:当前页号
 * @param pageSize:当前页总共的记录数
 * @return 该页的记录的List集合
 */
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”的方法,具体代码如下所示:

package com.ccff.mybatis.dao;

import com.ccff.mybatis.model.Course;

import java.util.List;
import java.util.Map;

public interface ICourseDao {
    //通过List结果集实现分页
    List<Course> getPageCourseByList();

    //通过SQL参数实现分页
    List<Course> getPageCourseBySQL(Map<String,Object> data);
}

3.2 添加SQL标签

  在CourseMapper.xml中添加select标签,具体代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<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。其源码如下:

package org.apache.ibatis.session;

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和Java的最大整数(2 147 483 647),使用它十分简单,只要给接口增加一个RowBounds参数即可。

4.1 添加接口方法

  在ICourseDao接口文件中创建名为“getPageCourseByRowBounds”的方法,具体代码如下所示:

package com.ccff.mybatis.dao;

import com.ccff.mybatis.model.Course;
import org.apache.ibatis.session.RowBounds;

import java.util.List;
import java.util.Map;

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标签,具体代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<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);
    }
}

  运行该测试方法后,查看控制台输出的日志信息如下,说明分页成功!
在这里插入图片描述
  这里需要注意RowBounds分页应用的场景,它只能应用于一些小数据量的查询。RowBounds分页的原理是执行SQL的查询后,按照偏移量和限制条数返回查询结果(即MyBatis对第一小节介绍的方法的一种实现,无需再重复造轮子),所以对于大数据量的数据查询,它的性能并不佳。此时可以通过分页插件去处理,详情参考下一小节。

5、通过插件实现分页

  关于MyBatis中插件的介绍在本系列博客的第十篇《MyBatis使用篇(十)—— MyBatis配置文件详解》中已经有了介绍。

  为了不重复造轮子,这里使用了PageHelper分页插件。PageHelper分页插件已经在GitHub上开源,PageHelper的GitHub地址

5.1 添加依赖jar包

  为了正确使用PageHelper分页插件,首先需要在WEB-INF/lib下导入其依赖的两个jar包:pagehelper-5.1.8.jar和jsqlparser-0.9.5.jar,并将其Add As Library。
在这里插入图片描述

5.2 配置分页插件

  想要在项目中使用PageHelper插件,则需要在全局配置文件中进行配置,具体配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<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>

  这里需要注意一个细节问题,就是关于PageHelper分页插件的版本的选择问题。本博客采用的是当前最新版本5.1.8。当使用4.x版本时,关于PageHelper插件的配置稍有不同,具体修改配置如下:

<!-- 配置分页插件 -->
<plugins>
    <plugin interceptor="com.github.pagehelper.PageInterceptor">
    <!-- 设置数据库类型 Oracle,Mysql,MariaDB,SQLite,Hsqldb,PostgreSQL六种数据库-->
    <property name="helperDialect" value="mysql"/>
    </plugin>
</plugins>

  如果使用5.x版本和如上配置则会报错,具体原理请参考:《使用MyBatis分页插件PageHelper遇到的问题》

5.3 添加接口方法

  在ICourseDao接口文件中创建名为“getPageCorseByPagePlugin”的方法,具体代码如下所示:

package com.ccff.mybatis.dao;

import com.ccff.mybatis.model.Course;
import org.apache.ibatis.session.RowBounds;

import java.util.List;
import java.util.Map;

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标签,具体代码如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<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);
    }
}

  运行该测试方法后,查看控制台输出的日志信息如下,说明分页成功!
在这里插入图片描述
  这里仅对PageHelper分页插件做了一个很简单的使用,如果感兴趣可自行查阅相关资料。
《(血和泪的成果)使用PageHelper分页插件进行后台分页》
《Mybatis 的分页插件PageHelper-4.1.1的使用》

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值