MyBatis
约 6983 字大约 23 分钟
2026-01-21
MyBatis 介绍
MyBatis 历史
原是 Apache 的一个开源项目 iBatis, 2010 年 6 月这个项目由 Apache Software Foundation 迁移到了 Google Code,随着开发团队转投 Google Code 旗下, iBatis3.x 正式更名为 MyBatis ,代码于 2013 年 11 月迁移到 Github(下载地址见后)
iBatis 一词来源于“internet”和“abatis”的组合,是一个基于 Java 的持久层框架。 iBatis 提供的持久层框架包括 SQL Maps 和 Data Access Obje
MyBatis 特点
- Mybatis 是一个半自动的 ORM(Object Relation Mapping)框架
- 面向接口编程思想:可以使用简单的 XML 或注解用于配置和原始映射,将接口和 Java 的实体类对象映射成数据库中的记录
- 支持定制化 SQL、存储过程以及==高级映射(一对多的映射关系)==的持久化框架
- 封装了几乎所有的 JDBC 代码和手动设置参数以及获取结果集
与其他持久化框架对比
- JDBC
- SQL 夹杂在 Java 代码中耦合度高,导致硬编码内伤。
- 维护不易且实际开发需求中 SQL 有变化,频繁修改的情况多见。
- 代码冗长,开发效率低。
- Hibernate 和 IPA
- 操作简便,开发效率高
- 程序中的长难复杂 SQL 需要绕过框架
- 内部自动生产的 SQL,不容易做特殊优化。
- 基于全映射的全自动框架,大量字段的 POJ0 进行部分映射时比较困难
- 反射操作太多,导致数据库性能下降
- MyBatis
- 轻量级,性能出色
- SQL 和 Java 编码分开,功能边界清晰。Java 代码专注业务、SQL 语句专注数据。
- 开发效率稍逊于 HIbernate,但是完全能够接受
对象关系映射——ORM
ORM 即 Object Relationship Mapping,对象关系映射!
| 解释/含义 | |
|---|---|
| 对象 | java 的实体类对象 |
| 关系 | 关系型数据库 |
| 映射 | 二者之间的对应关系 |
在 java 概念和数据库概念中的对应关系如下:
| java 概念 | 数据库概念 |
|---|---|
| 类 | 表 |
| 属性 | 字段/列 |
| 对象 | 记录/行 |
搭建 MyBatis
搭建一个基于 Maven 的 project
引入依赖
<dependencies>
<!-- Mybatis核心 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.10</version>
</dependency>
<!-- junit测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<!-- MySQL驱动 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.29</version>
</dependency>
<!-- log4j日志 -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>创建核心配置文件
- 习惯上命名为mybatis-config.xml,这个文件名仅仅只是建议,并非强制要求。
- 将来整合 Spring 之后,这个配置文件可以省略
- 核心配置文件主要用于配置连接数据库的环境以及 MyBatis 的全局配置信息核心配置文件存放的位置是src/main/resources目录下

创建表、实体类、mapper 接口

MyBatis 中的 mapper 接口相当于以前的 DAO 接口,但是区别在于, mapper 仅仅是接口,我们不需要提供实现类(面向接口编程);

创建映射文件
映射文件命名位置规则
- 表所对应的 实体类的类名+Mapper.xml ,例如:表 t_user,映射的实体类为 User,所对应的映射文件为 UserMapper.xml;放到 resources 目录下
- 因此一个映射文件对应一个实体类,对应一张表的操作;
- MyBatis 映射文件用于编写 SQL,访问以及操作表中的数据;
编写映射文件
MyBatis 中面向接口编程的两个一致:
==映射文件的namespace要和mapper接口的全类名保持一致====映射文件中SQL语句的id要和mapper接口中的方法名一致==

首先先根据核心配置文件中的来引入映射文件,再根据方法名匹配到 SQL 语句
修改核心配置文件中映射文件路径
若修改核心配置文件中的映射文件路径,则需将 UserMapper.xml 文件放置在 resources/mapper 文件夹下

Junit 测试

修改、删除、查询功能测试
- UserMapper.java

- UserMapper.xml

核心配置文件详讲
MyBatis核心配置文件中,标签的顺序
properties?,settings?,typeAliases?,typeHandlers?,
objectFactory?,objectWrapperFactory?,reflectorFactory?,
lugins?,environments?,databaseIdProvider?,mappers?environment、properties 讲解
<?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>
<!--
MyBatis核心配置文件中,标签的顺序:
properties?,settings?,typeAliases?,typeHandlers?,
objectFactory?,objectWrapperFactory?,reflectorFactory?,
plugins?,environments?,databaseIdProvider?,mappers?
-->
<!--引入properties文件,此时就可以${属性名}的方式访问属性值-->
<properties resource="jdbc.properties" />
<!--设置类型别名-->
<typeAliases>
<!--
typeAlias:设置某个类型的别名
属性:
type:设置需要设置别名的类型
alias:设置某个类型的别名,若不设置该属性,那么该类型拥有默认的别名,即类名且不区分大小写
-->
<!--<typeAlias type="com.atguigu.User"></typeAlias>-->
<!--以包为单位,将包下所有的类型设置默认的类型别名,即类名且不区分大小写-->
<package name="com.atguigu.mybatis.pojo"/>
</typeAliases>
<!--
environments:配置多个连接数据库的环境
属性:
default:设置默认使用的环境的id
-->
<environments default="development">
<!--
environment:配置某个具体的环境
属性:
id:表示连接数据库的环境的唯一标识,不能重复
-->
<environment id="development">
<!--
transactionManager:设置事务管理方式
属性:
type="JDBC|MANAGED"
JDBC:表示当前环境中,执行SQL时,使用的是JDBC中原生的事务管理方式,事务的提交或回滚需要手动处理
MANAGED:被管理,例如被Spring管理
-->
<transactionManager type="JDBC"/>
<!--
dataSource:配置数据源,与spring整合后不用再设置dataSource
属性:
type:设置数据源的类型
type="POOLED|UNPOOLED|JNDI"
POOLED:表示使用数据库连接池缓存数据库连接,即会将创建的连接进行缓存,下次使用可以从缓存中直接获取,不需要重新创建
UNPOOLED:表示不使用数据库连接池,即每次使用连接都需要重新创建
JNDI:表示使用上下文中的数据源
-->
<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>
<!--引入映射文件-->
<mappers>
<!--<mapper resource="mappers/UserMapper.xml"/>-->
<!--
以包为单位引入映射文件
要求:
1、mapper接口所在的包要和映射文件所在的包一致
2、mapper接口要和映射文件的名字一致
-->
<package name="com.atguigu.mybatis.mapper"/>
</mappers>
</configuration>typeAliases 讲解
作用:设置类型别名
<!-- 设置类型别名
方式一:以某一个类为单位(不常用)
方式二:以包为单位,将包下所有的类型设置为默认类型别名,即类型且不区分大小写(常用)
-->
<typeAliases>
<!--
方式一:
typeAlias:设置某个类型的别名
属性:
type:设置需要设置别名的类型
alias:设置某个类型的别名,如果不设置该属性,那么该类型拥有默认的别名,即类名而且不区分大小写
-->
<typeAlias type="com.peng.mybatis.pojo.User" alias="User"></typeAlias>
<!--
方式二:
-->
<package name="com.peng.mybatis.pojo.User"></package>
</typeAliases>mappers
将 UserMapper.xml 转移到新目录下

在 resources 包下面创建 directory(目录) 和创建 package(包) 是不一样的
不能用 com.peng.mybatis.mapper 这种方式创建多个文件夹,这样创建出来的是一个包名;应该用 com/peng/mybatis/mapper 这种方式。
在核心配置文件中引入映射文件
<!-- 引入映射文件
以包为单位引入映射文件
要求:mapper接口所在的包要和映射文件所在的包一致
mapper接口要和映射文件的名字一致
-->
<mappers>
<package name="com.peng.mybatis.mapper"/>
</mappers>MyBatis 获取参数值的两种方式
${}和#{}
MyBatis 获取参数值的两种方式:${}和#{}
- ${}本质为字符串替换
- #{}本质为占位符赋值
${}和#{}的相同点为都能获取参数变量的值,在预编译语法上则不同
| ${} | #{} | |
|---|---|---|
| 预编译 | 不行 | 将#{变量}编译成?,在执行时后再取值(自动加上引号),防止 sql 注入 |
| 应用场景 | 传入的参数是 sql 片段的场景 | 在 sql 映射文件中动态拼接 sql时的开发场景(获取变量) |
传入的参数是 sql 片段的场景
<select id="getUserPage" resultType="com.ymxx.oa.bean.User">
${sql片段}
</select>- 对于这样外部传入的 sql,就不能使用#{},上面也说了,#{}会进行预编译,检测到该 sql 片段是个字符串,就会加上引号,即'sql 片段',这样就是字符串了而不是 sql,执行会报错。
预编译过程
mybatis 在预编译过程大体上可以分为 数据类型检查和安全检查 两部分
数据类型检查:若检测到为数值类型,就不加引号,即?;若检测到位字符串类型,就加上引号,即'?'。
安全检查:若变量的值带有引号,会对引号进行转义处理==,这样可以防止 sql 注入
${}的 sql 注入问题
用${}时要特别注意 sql 注入的风险,如果该 sql 片段是根据用户的输入拼接的,要注意检查 sql 注入的问题,防止数据的泄露与丢失!
案例:
//sql语句
select * from ${tableName} where name = ${name}如果 tableName 的值为 user; delete user; --,该 sql 最终解析成
select * from user; delete user; -- where name = xxx结果查询了整张表,然后把 user 表给删了
获取参数值的各种情况
获取参数值的情况可以分为以下四种情况:
- 参数为单个的字面量类型
- 参数为多个时
- 使用原生的 map
- 使用自己的 map(${}、#{})
- 参数是实体类类型的参数
- 使用@Param 注解命名参数
参数为单个的字面量类型
- 可以通过{}和#{}以任意的字符串获取参数值 ,但是使用{}需要额外加上单引号
参数为多个时
使用原生的 map
- mybatis 会把形参的值放在一个 map 集合中,以两种方式进行存储
- 以arg0,arg1 为键或者以param0,param1 为键,
- 以参数值为值,可以混着用
使用自己的 map(${}、#{})
- 使用自己的 map 可以通过{}和#{}以键名的方式获取参数值== ,但是使用=={}需要额外加上单引号
- 可以==通过{}和#{}以自己设置的键名的方式获取参数值== ,但是使用{}需要额外加上单引号
参数是实体类类型的参数
- 通过${}和#{}以自己设置的键名(实体类里面的属性)的方式获取参数值
- 使用${}需要额外加上单引号
使用@Param 注解命名参数
- mybatis 会把形参的值放在一个 map 集合中,以两种方式进行存储
- 以自己使用的==@Param 注解的参数名为键或者以 param1,param2 为键==,
- 以参数值为值,可以混着用
举例
mapper 接口

映射文件

测试

小结
有实体类的时候直接用属性值来访问;
例如,如果有一个
User实体类,其中包含了id和name两个属性,那么在 SQL 语句中就可以直接引用这些属性:<select id="getUserById" resultType="User"> SELECT * FROM users WHERE id = #{id} </select>没有实体类的时候用 @Param 注解命名参数,不管字面量单个还是多个,是不是 map 集合都可以使用自己用注解定义的参数来访问。
当没有实体类或需要额外命名参数时,可以使用
@Param注解来命名参数。例如,假设我们需要在 SQL 中引用多个参数,可以这样做:- mapper 接口:
public interface UserMapper { List<User> getUsersByAgeRange(@Param("minAge") int minAge, @Param("maxAge") int maxAge); }映射文件:
<select id="getUsersByAgeRange" resultType="User"> SELECT * FROM users WHERE age BETWEEN #{minAge} AND #{maxAge} </select>
@Param 标识的源码解析
为啥我们能将我们想要的 key 值,以及对应的 value 值设置进去呢?
(1)首先看这个方法的第三步的内部是如何调用的?

(2) mapper 映射的底层使用了代理模式,通过反射执行当前命令对应的方法
- MapperProxy.java


(3)当前命令中,name 对应的是要执行的 sql 语句(唯一标识:mapper 映射文件中 namespace + id),方法对应的是 select 方法,所以 switch - case 直接跳到 select 方法去执行对应的方法:
- MapperMethod.java



这边在 else 模块中,第一个方法是将 args 参数转换成 sql 要求的参数,点进这个方法看一下里面怎么写的?

再进入方法内部,这个方法是一个将注解设定的命名规则的名称设置成 map 容器的 key 值的方法
- ParamNameResolver.java

第一步:name 是一个排序的 map 容器,其中 0 号位置放了我们通过注解命名的第一个参数名称,1 号位置放置了我们通过注解命名的第二个参数名称:
第二步:又因为我们有参数注解而且参数注解的个数不为 1,所以跳到 else 中执行,新建一个 map 容器用来放置 (键值,参数值);
第三步:遍历 names 这个 map 容器,取出其中第一个键值对;
第四步:将它的 value 值即放置的自定义的 username 注解名称当作键值,将 args[当前键值对的键值] 即 args[0] 当作 value 值放进 params 这个 map 容器中;

第五步:定义一个字符串 param1,这里的 1 表示的是遍历第一个键值对即 i = 0;
第六步:如果当前 names 这个 map 容器中没有包含当前的这个 param1 这个值(防止我们自己定义了,重复放置),那么我们就将(param1 ,args[0])这一个键值对放进 param 这个 map 容器中,也就是我们既可以用我们自己设定的 username 来访问对应的参数值,也可以用 param1 来访问对应的参数值。
第七步:i++,遍历 names 容器中的下一个键值对,重复执行 4 - 6;
第八步:最后将生成的 param 这个 map 容器返回,我们可以从中任意选择一个键值来访问对应的参数。
MyBatis 的各种查询功能
查询的数据只有一条
接收情况
若查询的数据只有一条,那可以分为以下三种情况:
- 通过实体类对象接收
- 通过 list 集合接收(建议使用 list 集合接收)
- 通过 map 集合接收
举例
- mapper 接口中方法的定义:

mapper 映射文件中 sql 语句的编写:
注意:通过map 集合接收的 sql 语句的 resultType 值 必须修改为 map

- 测试类

查询的数据有多条
若查询的数据有多条,那可以分为以下三种情况:
通过实体类类型的 list 集合接收
通过map 类型的 list 集合接收
通过注解@MapKey 注解实现注入
可以在 mapper 接口的方法上添加@MapKey 注解,此时就可以将每条数据转换为 map 集合作为值,以某个字段的值作为键,放在同一个 map 集合中
- mapper 接口中方法的定义

- mapper 映射文件中 sql 语句的编写:

- 测试

查询单个数据(聚合函数)
- mapper 接口中方法的定义:

- mapper 映射文件中 sql 语句的编写:

- 测试

补充:MyBatis 中设置了默认的类型别名,可以在 resultType 使用别名
java.lang.Integer --> int,integer int --> _int,_integer Map --> map String --> string
特殊 SQL 的执行
模糊查询
模糊查询语句:
select * from tb_user where username like '%鹏%';重点在如何解析出鹏字,由前面可知,${}本质为字符串替换、#{}本质为占位符(会进行预编译,若在数据类型检查中,检查为字符串类型,则会自动添加’‘引号)
mapper 映射文件中 sql 语句的编写,一共有三种方法可以实现:
- 使用${}
- 使用 concat和**#{}** 进行字符串拼接(推荐)
- 使用"%#{}%"
- mapper 接口中方法的定义:

- 映射文件:

这里不可以使用
select * from t_user where username like '%#{username}%',即将#{}这种占位符赋值获取参数值的放在 单引号 里面;这样直接将单引号里面的三个字符都当作字符串的一部分,而不会解析成占位符,看报错信息可以看出来,?直接放在单引号内部,当成一个==字符?==了,而不会被当成一个占位符。
解析结果:

- 测试

批量删除
- mapper 接口中方法的定义:

- mapper 映射文件中 sql 语句的编写,这里只能用 ${} 这种字符串替换的方法来实现:

- 不能使用 #{}这种方式:
#{}这种占位符赋值的方式,会自动给参数加上单引号
delete from t_user where id in (#{ids});
# in (1,2,3,4)——>in('1,2,3,4'),结果必定报错- 测试

动态设置表名
- mapper 接口中方法的定义:

- mapper 映射文件中 sql 语句的编写

- 测试

添加功能获取自增的主键
- mapper 接口中方法的定义:

- mapper 映射文件中 sql 语句的编写

- 测试

自定义映射 ResultMap
搭建 MyBatis 框架
数据库新建两张表 t_emp 和 t_dept,并存入测试数据
t_emp 表

t_dept 表和数据

新建两个类,其中 emp_name 对应的属性名为 empName

7.2 字段名和属性名不一致
解决字段名和属性名不一致的情况的三种方式
- 为字段名起别名
- 全局配置mapUnderscoreToCamelCase(驼峰映射)
- resultMap 设置自定义映射关系(推荐)
给字段名起别名

全局配置 mapUnderscoreToCamelCase
- mybatis-config.xml

ResultMap

多对一(从员工到部门)映射关系
定义:多对一的映射关系指的是一个对象(或实体)在关联另一个对象时,该对象拥有多个对应关联对象的情况。具体来说,多对一关系表示多个对象共同指向同一个对象
举例:假设有两个实体类 Department 和 Employee,一个部门可以有多名员工,而一名员工只能属于一个部门。在这种情况下,从 Employee 到 Department 的关系就是多对一的映射关系,因为多名员工可以指向同一个部门。
处理多对一的映射关系可以有以下几种方法:
通过 级联属性 赋值
通过 association 标签
通过 分步查询
通过级联属性(连接查询)赋值
- 员工对象

- 部门对象

- mapper 接口中方法定义

- mapper 映射文件

通过 association 标签
- mapper 映射文件

- 测试

通过分步查询(推荐)
通过 id 查询员工信息、并查出 did
- EmpMapper 接口方法定义

- EmpMapper.xml 映射文件

解释:
- association 标签中的 column 属性就将两个查询到的信息关联了起来;
- select 属性中写的是 mapper 接口的全类名(唯一标识);
通过 did 查询员工所对应的部门
- DeptMapper 接口方法定义

- DeptMapper.xml 映射配置文件,注意字段名和属性名并不相同

测试

分步查询的好处:延迟加载
可以实现 延迟加载,但是必须在核心配置文件中设置全局配置信息(配置如下两个信息):没有全局设置的话,默认的是立即加载;
lazyLoadingEnabled:延迟加载的全局开关。**当开启时,所有关联对象都会延迟加载;**需要 设置为 true,默认为 false。aggressiveLazyLoading:设置为 false,默认为 false。当开启时,任何方法的调用都会加载该对象的所有属性。 ,需要关闭他。关闭后每个属性会按需加载。
开启延迟加载之前

开启全局延迟加载之后
- mybatis-config.xml


可以局部关闭延迟加载
条件:全局延迟加载开启

一对多映射关系
- 定义:一对多关系表示一个对象指向多个相关联的对象
- 假设有两个实体类
Department和Employee,一个部门可以有多名员工,而一名员工只能属于一个部门。在这种情况下,从Department到Employee的关系就是一对多的映射关系,因为一个部门可以指向多名员工。
通过 collection 解决一对多映射关系
- DeptMapper 接口方法定义

- DeptMapper.xml 映射配置文件

- 测试

动态 SQL
在 MyBatis 中,可以使用动态 SQL 来根据条件生成不同的 SQL 语句
if:根据标签中test 属性所对应的表达式决定标签中的内容是否需要拼接到 SQL 语句中
where:
当 where 标签中有内容时,会自动生成 where 关键字,并且将内容前多余的 and 或者 or 去掉
当 where 标签中没有内容时,此时 where 标签没有任何效果
注意:where 标签不能将其中内容后面多余的 and 或者 or 去掉,只能将内容前多余的 and 或者 or 去掉
trim:
- prefix|suffix:将 trim 标签中内容前面或者后面添加指定内容
- prefixOverrides|suffixOverrides:将 trim 标签中内容前面或者后面去掉指定内容
- 若标签中没有任何内容时,trim 标签也没有任何效果
choose、when、otherwise
- 相当于 if...else if..else if....otherwise
- 其中 when 至少要有一个,otherwise 最多只能有一个
foreach
- collection:设置需要循环的数组或者集合
- item:表示数组或者集合中的每一个数据
- separator:循环体之间的分隔符\
- open:foreach 标签所循环的所有内容的开始符
- close:foreach 标签所循环的所有内容的结束符
if-where-trim 标签
if 标签

where 标签

trim 标签


choose-when-ohterwise 标签
choose、when、otherwise,相当于if…else if…else

foreach 标签
批量删除方式一

批量删除方式二

批量添加


SQL 标签
设置 SQL 片段:
<sql id="empColumns">eid,emp_name,age,sex,email</sql>引用 SQL 片段:
<include refid="empColumns"></include>

MyBatis 缓存
MyBatis 的一级缓存和二级缓存之间的主要区别:
作用域与可见性
- 一级缓存:是 SqlSession 级别的缓存,每个 SqlSession 都有自己独立的一级缓存,且缓存的数据对其他 SqlSession 是不可见的
- 二级缓存:是 Mapper 级别的缓存,它的作用域更广,可以被多个 SqlSession 共享
开启与配置
- 一级缓存:默认是开启的,无需进行任何配置即可使用
- 二级缓存:默认是关闭的,需要手动配置开启。开启二级缓存通常需要在 MyBatis 的配置文件中进行相应设置,并在 Mapper 的 XML 映射文件中使用 cache 标签 指定使用二级缓存
mybatis:
configuration:
cache-enabled: true<mapper namespace="com.example.mapper.MyMapper">
<cache/>
<select id="selectById" resultType="com.example.entity.MyEntity">
SELECT * FROM my_table WHERE id = #{id}
</select>
<!-- 其他 SQL 操作 -->
</mapper>数据存储与失效条件
- 一级缓存:数据存储在 SqlSession 对象中,通常是一个 HashMap 结构。当SqlSession 关闭、清空缓存、执行增删改操作或者手动清空缓存时,一级缓存会失效
- 二级缓存:数据存储在SqlSessionFactory 对象中,其生命周期更长。二级缓存的数据会在特定的条件下失效,例如缓存过期、数据被更新等。此外,二级缓存还需要考虑并发访问和数据同步的问题
适用场景与性能考虑
- 一级缓存:适用于在同一个 SqlSession 中频繁查询相同数据的情况。通过减少与数据库的交互次数,提高查询性能
- 二级缓存:适用于多个 SqlSession 之间需要共享查询结果的情况。虽然二级缓存可以提高性能,但由于其全局性和复杂性,需要谨慎使用,以避免出现数据不一致的问题
MyBatis 分页
使用步骤
- 在核心配置文件中配置分页插件
<plugins>
<!--设置分页插件-->
<plugin interceptor="com.github.pagehelper.PageInterceptor"></plugin>
</plugins>- 在 pom.xml 中添加依赖
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper</artifactId>
<version>5.2.0</version>
</dependency>测试
public class PageHelperTest {
/**
* limit index,pageSize
* index:当前页的起始索引
* pageSize:每页显示的条数
* pageNum:当前页的页码
*
* index=(pageNum-1)*pageSize
*
* 使用MyBaits的分页插件实现分页功能
* 1.需要在查询功能之前开启分页,2代表了当前页码,4代表当前页显示的数据
* PageHelper.startPage(2,4);
* 2.在查询功能之后获取分页相关信息
* PageInfo<Emp> page=new PageInfo<>(list,5);
* list代表分页数据
* 5代表当前导航分页的数量
*/
@Test
public void testPageHelper(){
try {
InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(is);
SqlSession sqlSession = sqlSessionFactory.openSession(true);
EmpMapper mapper = sqlSession.getMapper(EmpMapper.class);
//开启分页功能
//查询详细分页信息方式一:
// Page<Object> page = PageHelper.startPage(2, 4);
// System.out.println(page);
PageHelper.startPage(2,4);
//查询所有数据
List<Emp> list = mapper.selectByExample(null);
list.forEach(emp-> System.out.println(emp));
//查询详细分页信息方式二,其中5代表导航数
PageInfo<Emp> page=new PageInfo<>(list,5);
System.out.println(page);
} catch (IOException e) {
e.printStackTrace();
}
}
}Page<Object> page = PageHelper.startPage(2, 4);,这个函数返回的 page 是包含少量信息的 page 数据;PageInfo<Emp> page = new PageInfo<>(list, 5);,展示非常详细的 pageInfo 信息,里面包含 page 信息。

常用数据:
- pageNum:当前页的页码
- pageSize:每页显示的条数
- size:当前页显示的真实条数(有可能每页显示 5 条,但是最后一页只剩 2 条数据这样子)
- total:总记录数
- pages:总页数
- prePage:上一页的页码
- nextPage:下一页的页码
- isFirstPage/isLastPage:是否为第一页/最后一页
- hasPreviousPage/hasNextPage:是否存在上一页/下一页
- navigatePages:导航分页的页码数
- navigatepageNums:导航分页的页码,[1,2,3,4,5] --> -->
版权所有
版权归属:haipeng-lin