Mybatis

假如你一定要写注释,请确保它描述了离你最近的代码。

简介

官网:MyBatis 3 | 简介 – mybatis

MyBatis 是一款优秀的 持久层框架 ,用于简化 JDBC 开发

主要作用:

  • 封装了 JDBC 的繁琐操作(如连接管理、SQL 执行、结果映射)。
  • 通过 XML 或注解 配置 SQL 与 Java 对象的映射关系。

在分层架构中的位置:

1
Controller(控制层) → Service(业务层) → DAO(持久层) → 数据库
  • DAO(Data Access Object) :通过 MyBatis 与数据库交互。

Mybatis入门

快速入门

创建项目

新建一个SpringBoot项目用于Mybatis入门:

1756090140008

勾选Mybatis框架以及连接Mysql的驱动:

1756090162669

创建成功后项目中有这两个依赖:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- mybatis的起步依赖 -->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>

<!-- mysql数据库的连接驱动-->
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>

创建数据模型

假设数据库中有如下的用户表。

1756090765820

我们创建对应的用户类:Model/User.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class User {
private Integer id;
private String name;
private Short age;
private Short gender;
private String phone;

public User() {
}

public User(Integer id, String name, Short age, Short gender, String phone) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.phone = phone;
}

// 省略的getter与setter
}

配置Mybatis

配置Mybatis四要素:

要素 配置键 作用 示例值
驱动类名 spring.datasource.driver-class-name 指定 JDBC 驱动类,用于连接数据库 com.mysql.cj.jdbc.Driver
数据库 URL spring.datasource.url 定义数据库类型、地址、端口、库名及连接参数 jdbc:mysql://localhost:3306/mybatis
用户名 spring.datasource.username 数据库登录账号 root
密码 spring.datasource.password 数据库登录密码 1234

src/main/resources/application.properties

1
2
3
4
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mybatis
spring.datasource.username=root
spring.datasource.password=你的密码

编写SQL语句

Mapper/UserMapper.java

1
2
3
4
5
@Mapper
public interface UserMapper {
@Select("SELECT * FROM USER")
public List<User> selectAll();
}

声明一个接口并使用 @Mapper进行注解后,Mybatis会自动生成运行对象,并将对象交给IOC管理。调用对应的方法自动执行 @Select注解中的SQL语句,并将查询结构封装为对象返回。

测试程序

src/test/java/top/ulna520/mybatisquickstart/MybatisQuickStartApplicationTests.java

1
2
3
4
5
6
7
8
9
10
11
12
13
@SpringBootTest
class MybatisQuickStartApplicationTests {

@Autowired
private UserMapper userMapper;

@Test
void contextLoads() {
List<User> users = userMapper.selectAll();
users.forEach(System.out::println);
}

}

运行结果:

1
2
3
User{id=1, name='Alice', age=25, gender=2, phone='13800000001'}
User{id=2, name='Bob', age=30, gender=1, phone='13800000002'}
User{id=3, name='Charlie', age=28, gender=0, phone='13800000003'}

JDBC

定义

  • JDBC :Java DataBase Connectivity
  • 使用 Java 语言 操作 关系型数据库 的一套 API 规范

本质

  • Sun 公司官方定义的一套操作所有关系型数据库的 统一接口规范
  • 各数据库厂商根据规范提供 驱动实现类 (打包成驱动 jar 包)。
  • 开发者调用 JDBC 接口编程,真正执行的代码是驱动 jar 包中的实现类。

1756093565266

数据库连接池

数据库连接池是一个 容器 ,用于分配管理数据库连接(Connection 对象)。

作用

  • 复用已有连接,避免频繁创建/销毁连接带来的性能开销。
  • 统一管理连接的生命周期,防止连接泄漏。

1756094531971

核心机制

  1. 初始化 :启动时创建一定数量的数据库连接,存放在连接池中。
  2. 获取连接 :应用程序向连接池请求可用连接,而不是直接新建连接。
  3. 归还连接 :使用完毕后将连接放回连接池,而不是关闭物理连接。
  4. 回收机制
    • 空闲时间超过最大空闲时间的连接进行释放。
    • 避免因未释放连接导致的 连接泄漏

常见连接池

实现 特点
C3P0 较早期,稳定性好,性能一般
DBCP Apache 提供,配置简单
Druid 阿里巴巴开源,功能强大,性能优秀,监控能力强
HikariCP 高性能,轻量级,Spring Boot 默认连接池

更改数据库连接池:直接引入依赖

1
2
3
4
5
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>${druid-version}</version>
</dependency>

lombok

Lombok 是一个 Java 类库,通过注解自动生成常用方法(构造器、getter/setter、equals、hashCode、toString 等),并可自动生成日志变量。

作用:简化开发,减少样板代码,提高开发效率

注解 功能
@Getter / @Setter 所有属性生成 get / set 方法
@ToString 自动生成易读的 toString() 方法
@EqualsAndHashCode 根据类的非静态字段自动重写 equals()haMshCode() 方法
@Data 综合注解,等价于 @Getter + @Setter + @ToString + @EqualsAndHashCode
@NoArgsConstructor 生成无参构造方法
@AllArgsConstructor 生成包含所有字段(除 static 修饰字段)的全参构造方法

依赖示例:

1
2
3
4
5
6
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>最新版本</version>
<scope>provided</scope>
</dependency>

scope=provided 表示编译期可用,运行期不需要 Lombok.jar。

Mybatis-crud

首先我们准备一个Mapper注解接口:

1
2
3
4
@Mapper
public interface EmpMapper {

}

接下来我们写的增删改查都是其中的一个方法。

删除

SQL语句:

1
DELETE FROM emp WHERE id = 1;

接口方法:

1
2
@Delete("DELETE FROM emp WHERE id = #{id}")
public void delete(Integer id);

也可以是

1
2
@Delete("DELETE FROM emp WHERE id = #{id}")
public Integer delete(Integer id);

此时返回删除的数据条数。

打开Mypatis日志

application.properties

1
2
# 输出到控制台
mybatis.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl

Mybatis日志:

1756173793325

预编译SQL

普通 SQL vs 预编译 SQL:

特性 普通 SQL(Statement) 预编译 SQL(PreparedStatement)
SQL 发送次数 每次执行都发送完整 SQL 首次发送 SQL 模板,后续只传参数
编译次数 每次执行都重新解析、优化、编译 首次编译后缓存执行计划,后续复用
性能 多次重复执行时性能较低 多次重复执行时性能更高
安全性 易受 SQL 注入攻击 参数化传值,防止 SQL 注入
适用场景 一次性执行的 SQL 多次执行的相似 SQL
代码可维护性 需要频繁拼接字符串 SQL 模板与参数分离,结构清晰

1756174062701

SQL注入

采用普通SQL的语句:

1
SELECT COUNT(*) FROM user where username = '' AND password = '';

普通sql语句会直接将我们传入的用户名密码拼接到SQL语句中。

例如我们输入:ulna 123456

1
SELECT COUNT(*) FROM user where username = 'ulna' AND password = '123456';

但是如果我们输入:ulna 'OR '1'='1

1
SELECT COUNT(*) FROM user where username = 'ulna' AND password = '' OR '1' = '1';

此时由于 '1' = '1'条件恒成立,所以用户名和密码错误也可以登录成功。

参数占位符

写法 处理方式 是否预编译 安全性 典型用途
#{} 在执行 SQL 前会被替换为 ? 占位符,由 JDBC 进行参数绑定 ✅ 是 高(防 SQL 注入) 传递参数值(数字、字符串、日期等)
${} 在执行 SQL 前直接进行字符串拼接,将参数值原样拼入 SQL ❌ 否 低(易受 SQL 注入) 动态拼接表名、列名、排序字段等

新增

sql语句:

1
2
INSERT INTO emp(username, name, gender, /image, job, entrydate, dept_id, create_time, update_time)
VALUES('songyuanqiao', '宋元桥', '男', '1.jpg', '工程师', '2012-10-09', 2, '2022-10-01 00:00:00', '2022-10-01 00:00:00');

Mybatis接口方法示例:

1
2
3
@Insert("INSERT INTO emp(username, name, gender, /image, job, entrydate, dept_id, create_time, update_time) " +
"VALUES(#{username}, #{name}, #{gender}, #{/image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
void insert(Emp emp);

Mybatis日志:

1756176230932

主键返回

在数据添加成功后,需要获取插入数据库数据的主键

1
2
3
4
@Options(keyProperty = "id", useGeneratedKeys = true)
@Insert("INSERT INTO emp(username, name, gender, /image, job, entrydate, dept_id, create_time, update_time) " +
"VALUES(#{username}, #{name}, #{gender}, #{/image}, #{job}, #{entrydate}, #{deptId}, #{createTime}, #{updateTime})")
void insert(Emp emp);

@Options

  • useGeneratedKeys = true → 启用 JDBC 的自动生成主键功能
  • keyProperty = "id" → 指定实体类中接收主键的属性名

添加这个注解后,就会将自动生成的主键值封装到传入对象的 id属性中

更新

sql语句:

1
2
3
4
5
6
7
8
9
10
UPDATE emp
SET username = 'songdaxia',
name = '宋大侠',
gender = 1,
/image = '1.jpg',
job = 2,
entrydate = '2012-01-01',
dept_id = 2,
update_time = '2022-10-11 12:12:12'
WHERE id = 19;

接口方法:

1
2
@Update("UPDATE emp SET username=#{username}, name=#{name}, gender=#{gender}, /image=#{/image}, job=#{job}, entrydate=#{entrydate}, dept_id=#{deptId}, update_time=#{updateTime} WHERE id=#{id}")
void update(Emp emp);

查询

数据封装

在 MyBatis 中,Java 实体类(POJO)与数据库表字段之间的映射关系是数据持久化的核心。

如果字段名与列名不一致,MyBatis 无法自动映射,需要额外配置。

java实体类:

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Emp {
private Integer id;
private String username;
private String password;
private String name;
private String gender;
private String /image;
private String job;
private LocalDate entryDate;
private Integer deptId;
private LocalDateTime createTime;
private LocalDateTime updateTime;
}

数据库表:

1
2
3
4
5
6
7
8
9
10
11
12
13
CREATE TABLE emp (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(20),
password VARCHAR(20),
name VARCHAR(10),
gender CHAR(1),
/image VARCHAR(300),
job VARCHAR(10),
entry_date DATE,
dept_id INT UNSIGNED,
create_time DATETIME,
update_time DATETIME
);

默认规则 :Java 属性名与数据库列名 完全一致 时,MyBatis 会自动映射。

下划线转驼峰

  • 数据库列名:entry_date
  • Java 属性名:entryDate

方法一:给字段起别名

1
2
3
4
// 功能:给字段起别名,让取出与对象属性一致
@Select("select id, username, password, name, gender, mname, job, entrydate, " +
"dept_id deptId, create_time createTime, update_time updateTime from emp where id = #{id}")
public Emp getById(Integer id);

方法二@Results 注解

1
2
3
4
5
6
7
8
// 通过 @Results、@Result 注解手动映射封装
@Results({
@Result(column = "dept_id", property = "deptId"),
@Result(column = "create_time", property = "createTime"),
@Result(column = "update_time", property = "updateTime")
})
@Select("select * from emp where id = #{id}")
public Emp getById(Integer id);

方法三:开启Mybatis的驼峰命名与下划线自动映射开关(推荐)

1
2
# 驼峰命名与下划线命名自动映射开关
mybatis.configuration.map-underscore-to-camel-case=true

简单查询

SQL语句:

1
SELECT * FROM emp WHERE id = 1

Mybatis接口:

1
2
@Select("SELECT * FROM emp WHERE id = #{id}")
Emp selectById(Integer id);

只要我们开启了上述的自动映射,这里无需额外操作。

条件查询

示例:姓名模糊匹配 + 性别精确匹配 + 入职时间范围筛选 + 更新时间降序

SQL语句:

1
2
3
4
5
6
SELECT * 
FROM emp
WHERE name LIKE '%${name}%'
AND gender = #{gender}
AND entrydate BETWEEN #{begin} AND #{end}
ORDER BY update_time DESC;

Mybatis接口语句:

1
2
3
4
5
6
@Select("SELECT * FROM emp " +
"WHERE name LIKE '%${name}%' " +
"AND gender = #{gender} " +
"AND emp_date BETWEEN #{begin} AND #{end} " +
"ORDER BY update_time DESC")
public List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);

为什么不能直接使用#{name}

#{} 会被替换成 ? 占位符,'%#{name}%' 会变成:

1
WHERE name LIKE '%?%'

这是无效的 SQL,因为 ?放在 ''中不能被识别为参数。

解决办法:

  1. concat 或在 Java 代码里提前拼好 %
1
WHERE name LIKE CONCAT('%', #{name}, '%')
  1. 在Java传参前:
1
name = "%" + name + "%";

然后在SQL里直接:

1
WHERE name LIKE #{name}

参数说明

SpringBoot2.x 集成 MyBatis

  • 写法 :方法参数名可直接作为 SQL 占位符使用
  • 示例
1
2
3
4
5
6
@Select("SELECT * FROM emp " +
"WHERE name LIKE #{name} " +
"AND gender = #{gender} " +
"AND update_time BETWEEN #{begin} AND #{end} " +
"ORDER BY update_time DESC")
List<Emp> list(String name, Short gender, LocalDate begin, LocalDate end);

独立Mybatis(非 SpringBoot 环境)

  • 写法 :必须使用 @Param 显式绑定参数名
  • 示例
1
2
3
4
5
6
7
8
9
@Select("SELECT * FROM emp " +
"WHERE name LIKE CONCAT('%', #{name}, '%') " +
"AND gender = #{gender} " +
"AND update_time BETWEEN #{begin} AND #{end} " +
"ORDER BY update_time DESC")
List<Emp> list(@Param("name") String var1,
@Param("gender") Short var2,
@Param("begin") LocalDate var3,
@Param("end") LocalDate var4);

XML配置文件

XML映射文件规范:

  • 文件位置
    必须与 Mapper接口包名相同
  • namespace
    必须与 Mapper 接口的全限定类名 一致
    例:namespace="com.itheima.mapper.EmpMapper"
  • id
    必须与 Mapper 接口方法名 一致
    例:<select id="list"> 对应 EmpMapper.list(...)
  • resultType
    与方法返回值类型一致(通常是实体类全限定名)

实战示例

文件包名与位置:

1756181793871

基本结构:

1
2
3
4
5
6
7
<?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="top/ulna520/springbootmybatiscrud/Mapper/EmpMapper.java">

</mapper>

我们将这个方法改为XML配置:

1
2
@Select("SELECT * FROM emp WHERE id = #{id}")
Emp selectById(Integer id);

我们在xml中添加对应的Select配置:

1
2
3
4
5
6
7
8
9
<?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="top.ulna520.springbootmybatiscrud.Mapper.EmpMapper">
<select id="selectById" resultType="top.ulna520.springbootmybatiscrud.Model.Emp">
SELECT * FROM emp WHERE id = #{id}
</select>
</mapper>

然后将EmpMapper中的注解删除,只保留签名方法:

1
Emp selectById(Integer id);

插件推荐——MybatisX

1756182457140

安装插件后:

1756182701968

会自动匹配Mybatis接口与XML配置。可以点击左侧的小鸟图标方便的跳转。

动态SQL

动态 SQL 适用于根据用户输入或外部条件动态拼接查询语句的场景,常用于:

  • 多条件筛选(如姓名、性别、日期范围)
  • 后台管理系统的列表查询
  • 提高 SQL 灵活性,避免硬编码

if

用于判断条件是否成立。使用test属性进行条件判断,如果条件为true,则拼接SQL。

原始sql:

1
2
3
4
5
select * from pm_memo 
where title like concat('%', #{name}, '%')
and explore = #{explore}
and entrydate between #{fbegin} and #{fend}
order by update_time desc

使用if标签进行改造:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
 <select id="list" resultType="com.itheima.pojo.Emp">
select id, username, password, name, gender, /image, job,
entrydate, dept_id, create_time, update_time from emp
where
<if test="name != null">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
order by update_time desc
</select>

只有当test中的条件为ture时,<if>中的SQL语句才会被拼接。

但是此时如果所有的条件都为 false,就会导致存在 where但where中条件为空。SQL语句报错。

WHERE

  • 自动添加 WHERE 关键字 :当内部有条件时自动生成 WHERE,否则不生成。
  • 自动去除首个 AND / OR :避免 SQL 语法错误,如 WHERE AND ...
  • 提升 SQL 可读性与健壮性 :无需手动判断是否需要加 WHERE 或处理连接符。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<select id="list" resultType="com.itheima.pojo.Emp">
select id, username, password, name, gender, /image, job,
entrydate, dept_id, create_time, update_time from emp
<where>
<if test="name != null">
name like concat('%',#{name},'%')
</if>
<if test="gender != null">
and gender = #{gender}
</if>
<if test="begin != null and end != null">
and entrydate between #{begin} and #{end}
</if>
</where>
order by update_time desc
</select>

✅ 如果第一个条件没有 and,后续条件可以保留 and,MyBatis 会自动处理连接逻辑。

SET

在 MyBatis 中,<set></set> 标签主要用于 动态生成 SQL 的 SET 子句 ,尤其适合 UPDATE 语句。它的核心功能有两个:

  1. 自动去掉多余的逗号

    • 即使你在 <if></if> 中的 SQL 末尾加了 ,<set></set> 会帮你在生成 SQL 时去掉最后一个多余的逗号,避免语法错误。
  2. 条件更新

    • 结合 <if></if> 标签,只有在参数不为空(或满足条件)时,对应的字段才会出现在 SET 子句中,实现 部分字段的动态更新

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<update id="update2">
update emp
<set>
<if test="username != null">username = #{username},</if>
<if test="name != null">name = #{name},</if>
<if test="gender != null">gender = #{gender},</if>
<if test="/image != null">/image = #{/image},</if>
<if test="job != null">job = #{job},</if>
<if test="entrydate != null">entrydate = #{entrydate},</if>
<if test="deptId != null">dept_id = #{deptId},</if>
<if test="updateTime != null">update_time = #{updateTime}</if>
</set>
where id = #{id}
</update>

foreach

在 MyBatis 中,<foreach></foreach> 标签用于 遍历集合类型参数 ,动态生成 SQL 片段,常用于:

  • IN 查询(如批量删除、批量查询)
  • 批量插入
  • 拼接多个字段或条件

常见属性:

属性名 说明
collection 要遍历的集合名称(如 List、数组、或 Map 的某个键)
item 每次遍历的元素变量名
index 当前元素的索引(可选)
separator 每个元素之间的分隔符(如 ,
open 遍历开始前添加的字符串(如 (
close 遍历结束后添加的字符串(如 )

collection名称必须和传入参数一致,若是Map类型,要用 collection="mapKey"

示例:

接口方法:

1
public void deleteByIds(List<Integer> ids);

xml映射文件:

1
2
3
4
5
6
<delete id="deleteByIds">
delete from emp where id in
<foreach collection="ids" item="id" separator="," open="(" close=")">
#{id}
</foreach>
</delete>

sql&include

SQL 片段 (<sql></sql> 标签)

  • 用于定义可重用的 SQL 语句片段,避免多处重复编写相同列或条件。
  • 必须有唯一 id 作为引用标识

引用 SQL 片段 (<include></include> 标签)

  • 通过 refid 属性引入指定的 <sql></sql> 片段内容。
  • 会在编译映射文件时直接替换成对应 SQL 字符串。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<!-- ① 定义 SQL 片段 -->
<sql id="commonsSelect">
id, username, password, name, gender, /image, job, dept_id, create_time, update_time
</sql>

<!-- ② 在查询中引用 -->
<select id="list" resultType="com.thitima.pojo.Emp">
select
<include refid="commonsSelect"/>
from emp
<where>
<if test="name != null">
and name like #{name}
</if>
<if test="gender != null and gender != ''">
and gender = #{gender}
</if>
<if test="deptId != null">
and dept_id = #{deptId}
</if>
<if test="begin != null and end != null">
and create_time between #{begin} and #{end}
</if>
</where>
</select>

refid 必须匹配 :引用名应与 <sql id="..."></sql> 完全一致。

PageHelper

PageHelper 是一个基于 MyBatis 的无侵入式分页插件。它的核心作用是自动在SQL中追加分页语句(如 LIMIT),并提供分页信息封装、避免手写分页逻辑。

快速集成

1
2
3
4
5
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.4.7</version>
</dependency>

使用示例

创建简单查询语句

1
2
@Select("SELECT * FROM emp")
public List<Emp> list();

在Service层使用Pagehelper

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Service
public class EmpService {

@Autowired
public EmpMapper empMapper;

public List<Emp> findAll(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);

List<Emp> empList = empMapper.list();
Page<Emp> page = (Page<Emp>) empList;

return page.getResult();
}
}

PageHelper常用方法:

方法 作用 示例
startPage(int pageNum, int pageSize) 按页码分页 PageHelper.startPage(1, 10)
startPage(int pageNum, int pageSize, String orderBy) 分页并指定排序规则 PageHelper.startPage(1, 10, "id desc")
offsetPage(long offset, long limit) 按偏移量分页(适合无限滚动等场景) PageHelper.offsetPage(20, 10)
orderBy(String orderBy) 单独设置排序规则(不分页也可用) PageHelper.orderBy("create_time desc")
clearPage() 清除当前线程分页参数,避免影响后续查询 PageHelper.clearPage()

Page对象常用方法:

方法 返回值类型 说明
getResult() List<T> 当前页数据列表
getTotal() long 总记录数
getPages() int 总页数
getPageNum() int 当前页码
getPageSize() int 每页记录数
getStartRow() int 当前页起始行号(从 1 开始)
getEndRow() int 当前页结束行号
isCount() boolean 是否执行了 count 查询

PageInfo(对Page进行封装类)常用方法:

方法 返回值类型 说明
getList() List<T> 当前页数据
getTotal() long 总记录数
getPages() int 总页数
getPageNum() int 当前页码
getPageSize() int 每页记录数
isHasNextPage() boolean 是否有下一页
isHasPreviousPage() boolean 是否有上一页
getNavigatePages() int 导航页码数量(可配置)
getNavigatepageNums() int[] 导航页码数组
isIsFirstPage() boolean 是否为第一页
isIsLastPage() boolean 是否为最后一页

分页查询示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

public PageInfo<User> listUsers(int pageNum, int pageSize) {
// 1. 开启分页(自动作用于紧跟的第一条查询语句)
PageHelper.startPage(pageNum, pageSize, "create_time desc");

// 2. 执行查询(Mapper 方法不需要修改 SQL)
List<User> users = userMapper.selectAll();

// 3. 封装分页结果
return new PageInfo<>(users);
}

调用:

1
2
3
4
PageInfo<User> pageInfo = listUsers(2, 5);
System.out.println("总记录数: " + pageInfo.getTotal());
System.out.println("总页数: " + pageInfo.getPages());
System.out.println("当前页数据: " + pageInfo.getList());

Mybatis
http://blog.ulna520.com/2025/08/25/Mybatis_20250825_102037/
Veröffentlicht am
August 25, 2025
Urheberrechtshinweis