> 技术文档 > MyBatis-Plus 入门详解:从简介到 CRUD 实战

MyBatis-Plus 入门详解:从简介到 CRUD 实战


一、MyBatis-Plus 简介

1.1 什么是 MyBatis-Plus?

MyBatis-Plus(简称 MP)是 MyBatis 的增强工具,它在 MyBatis 的基础上只做增强、不做改变,核心目标是简化开发流程、提高开发效率。通过提供通用的 Mapper 和 Service,MP 可以让开发者在不编写任何 SQL 语句的前提下,快速实现单表的增删改查(CRUD)、批量操作、逻辑删除、分页等功能,是 MyBatis 的 “最佳搭档”。

 

1.2 核心特性

MyBatis-Plus 的特性可以用 “强大且贴心” 来概括,主要包括:

  • 无侵入性:引入后不会影响现有工程,使用方式与 MyBatis 无缝衔接;
  • 损耗小:启动时自动注入基本 CRUD 操作,性能几乎无损耗,直接面向对象编程;
  • 强大的 CRUD 操作:内置通用 Mapper 和 Service,少量配置即可实现单表大部分操作,配合条件构造器满足复杂查询需求;
  • Lambda 表达式支持:通过 Lambda 编写查询条件,避免字段名拼写错误;
  • 主键自动生成:支持 4 种主键策略(含分布式唯一 ID 生成器 Sequence),解决主键生成难题;
  • ActiveRecord 模式实体类继承 Model 类即可直接进行 CRUD 操作,简化代码;
  • 全局通用操作:支持全局通用方法注入,实现 “一次编写,多处使用”;
  • 内置工具:包括代码生成器(快速生成各层代码)、分页插件(支持多数据库)、性能分析插件(输出 SQL 及执行时间)、全局拦截插件(防止误操作)等。

1.3 支持的数据库

任何支持 MyBatis 且兼容标准 SQL 的数据库都可以使用 MyBatis-Plus,包括但不限于 MySQL、MariaDB、Oracle、DB2、H2、SQLite、PostgreSQL、SQLServer 等。

 

1.4 官方资源

  • 官方地址:http://mp.baomidou.com
  • 代码仓库:
    • Github:https://github.com/baomidou/mybatis-plus
    • Gitee:https://gitee.com/baomidou/mybatis-plus
  • 文档地址:https://baomidou.com/pages/24112f

二、MyBatis-Plus 入门案例

2.1 开发环境准备

  • IDE:IntelliJ IDEA 2017+
  • JDK:JDK 1.8
  • 构建工具:Maven 3.6.0+
  • MySQL:5.6(或 5.7、8.0)
  • Spring Boot:2.7.4
  • MyBatis-Plus:3.5.1

2.2 数据库与表设计

首先创建数据库和表,用于后续案例演示。

  1. 创建数据库
CREATE DATABASE `mybatis_plus` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;USE `mybatis_plus`;
  1. 创建用户表
CREATE TABLE `user` ( `id` bigint(20) NOT NULL COMMENT \'主键ID\', `name` varchar(30) DEFAULT NULL COMMENT \'姓名\', `age` int(11) DEFAULT NULL COMMENT \'年龄\', `email` varchar(50) DEFAULT NULL COMMENT \'邮箱\', PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8;
  1. 插入测试数据
INSERT INTO user (id, name, age, email) VALUES(1, \'Jone\', 18, \'test1@baomidou.com\'),(2, \'Jack\', 20, \'test2@baomidou.com\'),(3, \'Tom\', 28, \'test3@baomidou.com\'),(4, \'Sandy\', 21, \'test4@baomidou.com\'),(5, \'Billie\', 24, \'test5@baomidou.com\');

 

2.3 创建 Spring Boot 工程

2.3.1 初始化工程

使用 Spring Initializr(https://start.spring.io/)快速创建一个 Spring Boot 工程,选择必要的基础依赖(如 Spring Web)。

 

2.3.2 引入核心依赖

pom.xml中添加 MyBatis-Plus、Lombok、MySQL 驱动依赖:

 com.baomidou mybatis-plus-boot-starter 3.5.1 org.projectlombok lombok true mysql mysql-connector-java runtime
2.3.3 安装 Lombok 插件

IDEA 中需安装 Lombok 插件(File -> Settings -> Plugins,搜索 Lombok 并安装),否则会提示注解相关错误。要重启

 

2.4 编写核心代码

2.4.1 配置数据源(application.yml)

配置数据库连接信息,注意 MySQL 版本差异:

spring: datasource: type: com.zaxxer.hikari.HikariDataSource # Spring Boot 2.x默认连接池 driver-class-name: com.mysql.cj.jdbc.Driver # MySQL 8.0+推荐使用此驱动(5.x可用com.mysql.jdbc.Driver) url: jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8 # MySQL 8.0需指定时区 username: root password: 你的数据库密码# 配置MyBatis日志(可选,用于查看SQL执行过程)mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

1、驱动类driver-class-name

spring boot 2.0(内置jdbc5驱动),驱动类使用

driver-class-name: com.mysql.jdbc.Driver

spring boot 2.1及以上(内置jdbc8驱动),驱动类使用:

driver-class-name: com.mysql.cj.jdbc.Driver

否则运行测试用例的时候会有 WARN 信息

2、连接地址url

MySQL5.7版本的url

jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false

MySQL8.0版本的url

jdbc:mysql://localhost:3306/mybatis_plus?

serverTimezone=GMT%2B8&characterEncoding=utf-8&useSSL=false

否则运行测试用例报告如下错误:

java.sql.SQLException: The server time zone value\'Öйú±ê׼ʱ¼ä\' is unrecognized or represents more

mysql 5和8 的驱动类取决与springboot是否是2.1之前的版本。
要是8 就是com.mysql.cj.jdbc.Driver
要是5 就是com.mysql.jdbc.Driver
和本地的版本无关
其次,
url是和本地的mysql版本有关。8以上就要加时区

 

2.4.2 启动类(添加 Mapper 扫描)

在启动类上添加@MapperScan注解,指定 Mapper 接口所在的包路径:

import org.mybatis.spring.annotation.MapperScan;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication@MapperScan(\"com.example.mybatisplus.mapper\") // 扫描Mapper接口包public class MybatisPlusApplication { public static void main(String[] args) { SpringApplication.run(MybatisPlusApplication.class, args); }}
2.4.3 实体类(User.java)

使用 Lombok 注解简化 getter、setter、构造器等代码:

import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data // 自动生成getter、setter、toString等@AllArgsConstructor // 全参构造器@NoArgsConstructor // 无参构造器public class User { private Long id; private String name; private Integer age; private String email;}

 

2.4.4 Mapper 接口(UserMapper.java)

继承 MyBatis-Plus 提供的BaseMapper,无需编写方法即可获得 CRUD 能力:

import com.baomidou.mybatisplus.core.mapper.BaseMapper;import com.example.mybatisplus.entity.User;import org.springframework.stereotype.Repository;@Repository // 标记为Spring数据访问层组件,避免IDE报错public interface UserMapper extends BaseMapper { // 无需编写方法,BaseMapper已提供所有基础CRUD操作}

2.5 测试 CRUD 操作

通过 Spring Boot 测试类验证 MyBatis-Plus 的 CRUD 功能,注入UserMapper后直接调用方法即可。

package com.qcby.springbootmybitasplus;import com.baomidou.mybatisplus.test.autoconfigure.MybatisPlusTest;import com.qcby.springbootmybitasplus.entity.User;import com.qcby.springbootmybitasplus.mapper.UserMapper;import org.junit.jupiter.api.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest//@MybatisPlusTestclass SpringbootMybitasPlusApplicationTests { @Autowired private UserMapper userMapper; @Test public void testSelectList(){//selectList()根据MP内置的条件构造器查询一个list集合,null表示没有条件,即查询所有 userMapper.selectList(null).forEach(System.out::println); }}

 

Bean对象,但是可以正常读取数据正常运行在测试mybatis plus 的mapper时,自己的mapper接口不加@Repository注解为什么会提示找不到具体
 

IDEAuserMapper 处报错,因为找不到注入的对象,因为类是动态创建的,但是程序可以正确 的执行。

为了避免报错,可以在mapper接口上添加 @Repository 注解

 

添加日志

mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

 BaseMapper

 MyBatis-Plus中的基本CRUD在内置的BaseMapper中都已得到了实现,我们可以直接使用,接口如下:

package com.baomidou.mybatisplus.core.mapper; public interface BaseMapper extends Mapper { /** * 插入一条记录 * @param entity 实体对象 */ int insert(T entity); /** * 根据 ID 删除 * @param id 主键ID */ int deleteById(Serializable id); /** * 根据实体(ID)删除 * @param entity 实体对象 * @since 3.4.4 */ int deleteById(T entity); /** * 根据 columnMap 条件,删除记录 * @param columnMap 表字段 map 对象 */ int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap); /** * 根据 entity 条件,删除记录 * @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ int delete(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** * 删除(根据ID 批量删除) * @param idList 主键ID列表(不能为 null 以及 empty) */ int deleteBatchIds(@Param(Constants.COLLECTION) Collection idList); /** * 根据 ID 修改 * @param entity 实体对象 */ int updateById(@Param(Constants.ENTITY) T entity); /** * 根据 whereEntity 条件,更新记录 * @param entity 实体对象 (set 条件值 ,可以为 null) * @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) */ int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper); /** * 根据 ID 查询 * @param id 主键ID */ T selectById(Serializable id); /** * 查询(根据ID 批量查询) * @param idList 主键ID列表(不能为 null 以及 empty) */ List selectBatchIds(@Param(Constants.COLLECTION) Collection idList); /** * 查询(根据 columnMap 条件) * @param columnMap 表字段 map 对象 */ List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap); /** * 根据 entity 条件,查询一条记录 * 

查询一条记录,例如 qw.last(\"limit 1\") 限制取一条记录 , 注意:多条数据会报异常

* @param queryWrapper 实体对象封装操作类(可以为 null) */ default T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper) { List ts = this.selectList(queryWrapper); if (CollectionUtils.isNotEmpty(ts)) { if (ts.size() != 1) { throw ExceptionUtils.mpe(\"One record is expected, but the query result is multiple records\"); } return ts.get(0); } return null; } /** * 根据 Wrapper 条件,查询总记录数 * @param queryWrapper 实体对象封装操作类(可以为 null) */ Long selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** * 根据 entity 条件,查询全部记录 * @param queryWrapper 实体对象封装操作类(可以为 null) */ List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** * 根据 Wrapper 条件,查询全部记录 * @param queryWrapper 实体对象封装操作类(可以为 null) */ List<Map> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** * 根据 Wrapper 条件,查询全部记录 *

注意: 只返回第一个字段的值

* @param queryWrapper 实体对象封装操作类(可以为 null) */ List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper); /** * 根据 entity 条件,查询全部记录(并翻页) * @param page 分页查询条件(可以为 RowBounds.DEFAULT) * @param queryWrapper 实体对象封装操作类(可以为 null) */ <P extends IPage> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper); /** * 根据 Wrapper 条件,查询全部记录(并翻页) * @param page 分页查询条件 * @param queryWrapper 实体对象封装操作类 */ <P extends IPage<Map>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);}

基本CRUD 

1. 插入一条记录

/*** 插入一条记录* @param entity 实体对象 */int insert(T entity);
测试代码
@Testpublic void testInsert(){ User user = new User(null, \"张三\", 23, \"zhangsan@qcby.com\"); // 执行的SQL:INSERT INTO user ( id, name, age, email ) VALUES ( ?, ?, ?, ? ) int result = userMapper.insert(user); System.out.println(\"受影响行数:\"+result); // 输出示例:1475754982694199298 System.out.println(\"id自动获取:\"+user.getId());}

说明

执行后会自动生成 ID(示例结果:1903360524240498689),这是因为 MyBatis-Plus 默认使用雪花算法生成主键 ID,可保证分布式环境下的 ID 唯一性。

 

2. 删除操作

2.1 根据 ID 删除

原码
/*** 根据 ID 删除* @param id 主键ID */int deleteById(Serializable id);
测试代码
@Testpublic void testDeleteById(){ // 通过id删除用户信息,执行的SQL:DELETE FROM user WHERE id=? int result = userMapper.deleteById(1903360524240498689L); System.out.println(\"受影响行数:\"+result);}

 

2.2 根据实体(ID)删除

原码
/*** 根据实体(ID)删除* @param entity 实体对象* @since 3.4.4 */int deleteById(T entity);
测试代码
/** * 根据用户ID删除(通过实体对象传递ID) */@Testpublic void deleteByUserID(){ int result = userMapper.deleteById(8L); // 此处直接传入ID(本质与2.1一致,也可传入含ID的实体对象) System.out.println(\"受影响的行数:\"+result);}

 

2.3 根据 columnMap 条件删除

原码
/*** 根据 columnMap 条件,删除记录* @param columnMap 表字段 map 对象 */int deleteByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
测试代码
@Testpublic void testDeleteByMap(){ // 根据map集合中设置的条件删除记录,执行的SQL:DELETE FROM user WHERE name = ? AND age = ? Map map = new HashMap(); map.put(\"age\", 23); // 条件1:age=23 map.put(\"name\", \"张三\"); // 条件2:name=张三 int result = userMapper.deleteByMap(map); System.out.println(\"受影响行数:\"+result);}

 

2.4 根据 entity 条件删除

原码
/*** 根据 entity 条件,删除记录* @param queryWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)*/int delete(@Param(Constants.WRAPPER) Wrapper queryWrapper);
测试代码
/** * 根据entity条件删除记录 */@Testpublic void deleteByEntity(){ User user = new User(); user.setName(\"nn\"); // 条件1:name=nn user.setAge(22); // 条件2:age=22 // 用QueryWrapper封装条件(基于实体对象) QueryWrapper queryWrapper = new QueryWrapper(user); int result = userMapper.delete(queryWrapper); System.out.println(\"受影响的行数:\"+result);}

 

2.5 根据 ID 批量删除

原码
/*** 删除(根据ID 批量删除)* @param idList 主键ID列表(不能为 null 以及 empty) */int deleteBatchIds(@Param(Constants.COLLECTION) Collection idList);
测试代码
@Testpublic void testDeleteBatchIds(){ // 通过多个id批量删除,执行的SQL:DELETE FROM user WHERE id IN ( ? , ? , ? ) List idList = Arrays.asList(1L, 2L, 3L); // 要删除的ID列表 int result = userMapper.deleteBatchIds(idList); System.out.println(\"受影响行数:\"+result);}

 

3. 修改操作

3.1 根据 ID 修改

原码
/*** 根据 ID 修改* @param entity 实体对象 */int updateById(@Param(Constants.ENTITY) T entity);
测试代码
@Testpublic void testUpdateById(){ User user = new User(4L, \"admin\", 22, null); // 仅修改非null字段(id为条件,name和age为修改值) // 执行的SQL:UPDATE user SET name=?, age=? WHERE id=? int result = userMapper.updateById(user); System.out.println(\"受影响行数:\"+result);}

3.2 根据 whereEntity 条件更改

原码
/*** 根据 whereEntity 条件,更新记录* @param entity 实体对象 (set 条件值,可以为 null)* @param updateWrapper 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句)*/int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper updateWrapper);
测试代码
/** * 根据whereEntity条件更新 */@Testpublic void testUpdateByWhere(){ User updateUser = new User(); updateUser.setName(\"Updated\"); // 要修改的字段1:name=Updated updateUser.setAge(30); // 要修改的字段2:age=30 User oldUser = new User(); oldUser.setName(\"丽丽\"); // 条件1:name=丽丽 oldUser.setAge(33); // 条件2:age=33 // 用UpdateWrapper封装更新条件(基于oldUser) UpdateWrapper updateWrapper = new UpdateWrapper(oldUser); int result = userMapper.update(updateUser, updateWrapper); System.out.println(\"受影响行数:\"+result);}

 

4. 查询操作

4.1 根据 ID 查询

原码
/*** 根据 ID 查询* @param id 主键ID */T selectById(Serializable id);
测试代码
@Testpublic void testSelectById(){ // 根据id查询用户信息,执行的SQL:SELECT id,name,age,email FROM user WHERE id=? User user = userMapper.selectById(4L); System.out.println(user);}

 

4.2 根据 ID 批量查询

原码
/*** 查询(根据ID 批量查询)* @param idList 主键ID列表(不能为 null 以及 empty) */List selectBatchIds(@Param(Constants.COLLECTION) Collection idList);
测试代码
@Testpublic void testSelectBatchIds(){ // 根据多个id查询多个用户信息,执行的SQL:SELECT id,name,age,email FROM user WHERE id IN ( ? , ? ) List idList = Arrays.asList(4L, 5L); // 要查询的ID列表 List list = userMapper.selectBatchIds(idList); list.forEach(System.out::println); // 用Lambda表达式遍历输出}

 

4.3 根据 columnMap 条件查询

原码
/*** 查询(根据 columnMap 条件)* @param columnMap 表字段 map 对象 */List selectByMap(@Param(Constants.COLUMN_MAP) Map columnMap);
测试代码
@Testpublic void testSelectByMap(){ // 通过map条件查询用户信息,执行的SQL:SELECT id,name,age,email FROM user WHERE name = ? AND age = ? Map map = new HashMap(); map.put(\"age\", 22); // 条件1:age=22 map.put(\"name\", \"admin\"); // 条件2:name=admin List list = userMapper.selectByMap(map); list.forEach(System.out::println);}

 

4.4 根据 entity 条件查询一条记录

原码
/*** 根据 entity 条件,查询一条记录* 

查询一条记录,例如 qw.last(\"limit 1\") 限制取一条记录,注意:多条数据会报异常

* @param queryWrapper 实体对象封装操作类(可以为 null)*/default T selectOne(@Param(Constants.WRAPPER) Wrapper queryWrapper) { List ts = this.selectList(queryWrapper); if (CollectionUtils.isNotEmpty(ts)) { if (ts.size() != 1) { throw ExceptionUtils.mpe(\"One record is expected, but the query result is multiple records\"); } return ts.get(0); } return null;}

 

测试代码
  • 多条记录时(会报错)

    @Testpublic void testSelectByEntity(){ User user = new User(); user.setAge(22); // 假设满足age=22的记录有2条 QueryWrapper queryWrapper = new QueryWrapper(user); System.out.println(userMapper.selectOne(queryWrapper)); // 抛出异常:期望1条记录,但查询到多条}
  • 单条记录时(正常返回)

    @Testpublic void testSelectByEntity(){ User user = new User(); user.setAge(30); user.setName(\"Updated\"); // 假设满足age=30且name=Updated的记录只有1条 QueryWrapper queryWrapper = new QueryWrapper(user); System.out.println(userMapper.selectOne(queryWrapper)); // 正常返回该记录}

 

4.5 根据 wrapper 条件查询总记录数

原码
/*** 根据 Wrapper 条件,查询总记录数* @param queryWrapper 实体对象封装操作类(可以为 null) */Long selectCount(@Param(Constants.WRAPPER) Wrapper queryWrapper);
测试代码
/** * 根据Wrapper条件查询总记录数 */@Testpublic void testByWrapper(){ User user = new User(); user.setAge(22); // 条件:age=22 QueryWrapper queryWrapper = new QueryWrapper(user); System.out.println(userMapper.selectCount(queryWrapper)); // 输出满足条件的记录总数}

 

4.6 根据 entity 条件查询全部记录

原码
/*** 根据 entity 条件,查询全部记录* @param queryWrapper 实体对象封装操作类(可以为 null) */List selectList(@Param(Constants.WRAPPER) Wrapper queryWrapper);
测试代码
@Testpublic void testSelectList1(){ // 查询所有用户信息,执行的SQL:SELECT id,name,age,email FROM user List list = userMapper.selectList(null); // null表示无查询条件(查询全部) list.forEach(System.out::println);}

 

4.7 根据 wrapper 条件查询全部记录(封装为 Map)

原码
/*** 根据 Wrapper 条件,查询全部记录* @param queryWrapper 实体对象封装操作类(可以为 null) */List<Map> selectMaps(@Param(Constants.WRAPPER) Wrapper queryWrapper);
测试代码
/** * 根据wrapper条件查询全部记录(结果封装为Map) */@Testpublic void testDelectMaps(){ List<Map> resultList = userMapper.selectMaps(null); // 查询全部,结果为Map列表 // 输出查询结果(Map的key为表字段名,value为字段值) for (Map result : resultList) { System.out.println(result); }}

 

4.8 根据 wrapper 条件查询全部记录(返回第一个字段值)

原码
/*** 根据 Wrapper 条件,查询全部记录* 

注意: 只返回第一个字段的值

* @param queryWrapper 实体对象封装操作类(可以为 null) */List selectObjs(@Param(Constants.WRAPPER) Wrapper queryWrapper);
测试代码
/** * 根据wrapper条件查询全部记录,只返回第一个字段的值 */@Testpublic void testSelectObjs(){ List resultObjs = userMapper.selectObjs(null); // 查询全部,只返回每条记录的第一个字段(此处为id) for(Object o : resultObjs){ System.out.println(o); // 输出所有id }}

 

4.9 根据 entity 条件查询全部记录并翻页

原码
/*** 根据 entity 条件,查询全部记录(并翻页)* @param page 分页查询条件(可以为 RowBounds.DEFAULT)* @param queryWrapper 实体对象封装操作类(可以为 null) */<P extends IPage> P selectPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);
测试代码
/** * 根据entity条件查询并翻页 */@Testpublic void testSelectPage(){ Page p = new Page(1, 5); // 第1页,每页5条记录 IPage results = userMapper.selectPage(p, null); // 无查询条件,查询全部并分页 // 输出分页信息 System.out.println(\"当前页: \" + results.getCurrent()); System.out.println(\"每页记录数: \" + results.getSize()); System.out.println(\"总记录数: \" + results.getTotal()); System.out.println(\"总页数: \" + results.getPages()); // 输出当前页的记录(getRecords()获取分页数据列表) results.getRecords().forEach(user -> System.out.println(user));}

 

4.10 根据 wrapper 条件查询全部记录并翻页(封装为 Map)

原码
/*** 根据 Wrapper 条件,查询全部记录(并翻页)* @param page 分页查询条件* @param queryWrapper 实体对象封装操作类 */<P extends IPage<Map>> P selectMapsPage(P page, @Param(Constants.WRAPPER) Wrapper queryWrapper);
测试代码
/** * 根据wrapper条件查询并翻页(结果封装为Map) */@Testpublic void testSelectMapsPage(){ Page<Map> page = new Page(); // 默认第1页,每页10条 IPage<Map> results = userMapper.selectMapsPage(page, null); // 无查询条件,分页查询全部 // 输出分页信息 System.out.println(\"当前页: \" + results.getCurrent()); System.out.println(\"每页记录数: \" + results.getSize()); System.out.println(\"总记录数: \" + results.getTotal()); System.out.println(\"总页数: \" + results.getPages()); // 输出当前页的记录(Map格式) results.getRecords().forEach(record -> System.out.println(record));}

 

三、核心概念补充

3.1 BaseMapper 详解

BaseMapper是 MP 的核心接口,封装了 17 个常用 CRUD 方法,泛型T为实体类类型。主要方法包括:

  • insert(T entity):插入
  • deleteById(Serializable id):按 ID 删除
  • updateById(T entity):按 ID 更新
  • selectById(Serializable id):按 ID 查询
  • selectList(Wrapper wrapper):条件查询列表
  • selectPage(IPage page, Wrapper wrapper):分页查询

3.2 @MapperScan 与 @Repository 的区别

  • @MapperScan:MyBatis-Plus 注解,用于扫描指定包下的 Mapper 接口,自动生成代理实现类并注册为 Spring Bean;
  • @Repository:Spring 注解,标记接口为数据访问层组件,仅用于消除 IDE 的 “未注入” 警告,不影响功能。

四、MapperScan和repository的区别

接口的代理实现类是由框架来提供的,所以我们需要配置一个单独扫描mapper的扫描器。

@MapperScan是 MyBatis-Spring 框架里的注解。MyBatis 是一个优秀的持久层框架,而 MyBatis-Spring 则让 MyBatis 能更好地集成到 Spring 框架中。

        作用:它的作用是扫描指定包下的所有接口,并把这些接口自动注册为 MyBatis 的 Mapper Bean。这样一来,我们就无需在每个 Mapper 接口上单独添加@Mapper注解了。

@Repository是 Spring 框架自带的注解。

        将类(这个接口的代理类)交给Spring去管理,而这个代理类是由mybatisPlus(MyBatis的增强,还是MyBatis)实现的。管理着它的实现类,要是没有这个注解,就需要userMapperImpl,但是mybatisPlus框架都给提供了。

        如果不加,他会报波浪线,但是不出错。

        如果这个接口有很多实现类,加了@Repository注解,就明确告诉它,用的是框架提供的实现类。