文章目录
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的使用》