数据库学习入门(Spring Boot入门:MyBatis-Plus进阶,搞定复杂数据库操作)

数据库学习入门(Spring Boot入门:MyBatis-Plus进阶,搞定复杂数据库操作)
Spring Boot入门:MyBatis-Plus进阶,搞定复杂数据库操作

在前文内容中,我们完成了Spring Boot整合MyBatis-Plus的基础实操,掌握了实体类、Mapper、Service、Controller的编写规范,以及如何调用MyBatis-Plus内置方法实现简单的CRUD操作,成功迈出了数据库操作的第一步。

但在实际基础开发中,简单的CRUD远远不够——比如查询商品时需要“分页显示”(避免数据过多加载缓慢),查询用户时需要“按条件筛选”(如按年龄、邮箱查询),这些都是零基础入门后,必须掌握的核心进阶技能。今天,我们进入Spring Boot学习MyBatis-Plus基础进阶内容:分页查询与条件查询实操。

本文全程贴合“从基础到入门”导向,完全衔接MyBatis-Plus整合项目(springboot-basic),无需重新搭建环境,摒弃复杂的底层原理,聚焦“零基础能看懂、能实操”,手把手教你配置分页插件、编写条件查询代码,每一步都搭配具体代码示例和效果验证,让你快速掌握复杂数据库操作的核心方法,进一步夯实数据库开发基础,为编写完整业务项目(如商品管理、用户管理)打下坚实基础。

学习建议:本文适合已掌握MyBatis-Plus基础CRUD操作的零基础学习者,建议结合上一篇搭建的springboot-basic项目同步实操,跟着步骤一步步配置、编写代码,重点理解“分页插件的配置逻辑”和“条件查询的用法”,无需死记硬背,实操落地就能轻松掌握,逐步实现从“简单CRUD”到“复杂查询”的跨越。

入门必懂:为什么要学分页+条件查询?实际开发刚需

很多零基础学习者会疑惑:上一篇已经掌握了CRUD,为什么还要学分页和条件查询?这两个功能在实际开发中到底有什么用?搞懂这些,能让我们更清晰地理解学习的意义,贴合实际开发需求,避免盲目学习。

1.1 分页查询:解决“数据过多”的痛点

在实际开发中,数据库表中的数据往往很多(如商品表可能有上万条数据),如果直接查询所有数据,会导致以下问题:

1. 加载缓慢:一次性加载大量数据,会占用过多的内存和网络资源,导致接口响应缓慢,影响用户体验;

2. 数据混乱:大量数据一次性展示,用户无法快速找到自己需要的内容,不符合实际使用场景。

分页查询的核心作用的是“分批次加载数据”(如每页显示10条、20条),既减轻服务器压力,又提升用户体验,是基础开发中不可或缺的功能(如电商平台的商品列表、后台管理系统的用户列表,都用到了分页)。

1.2 条件查询:解决“精准筛选”的痛点

简单的“查询所有”“查询单个”无法满足实际开发需求——比如用户需要查询“年龄大于20岁的用户”“邮箱包含163.com的用户”,管理员需要查询“特定时间段注册的用户”,这些都需要通过条件查询实现。

MyBatis-Plus提供了简洁的条件查询API(QueryWrapper),无需编写复杂SQL,就能实现多条件组合查询,大幅简化开发,适配零基础入门者的学习节奏,也是企业基础开发中高频使用的功能。

1.3 学习重点(零基础必抓)

本文聚焦MyBatis-Plus进阶的2个核心内容,无需深入底层原理,重点掌握以下3点,就能应对80%的复杂数据库查询场景:

1. 分页查询:配置MyBatis-Plus分页插件,编写分页查询代码,实现数据分批次加载;

2. 条件查询:使用QueryWrapper构建查询条件,实现多条件组合查询(如等于、大于、模糊查询);

3. 综合实操:结合分页+条件查询,实现“按条件筛选并分页显示”,贴合实际开发场景。

前置准备(衔接前文,无需重新搭建)

本次实操将完全衔接第十七个热点搭建的“springboot-basic”项目,无需重新创建项目,无需修改原有代码,只需确保以下3个前置条件满足,即可顺利开展实操:

1. 已完成Spring Boot整合MyBatis-Plus(参考第十七个热点),能正常实现CRUD操作;

2. 已创建user表,并添加多条测试数据(至少10条,方便测试分页效果,可手动插入或通过上一篇的新增接口批量添加);

3. 项目已引入MyBatis-Plus核心依赖、MySQL驱动依赖(上一篇已配置,无需重复操作)。

补充:若未添加测试数据,可通过上一篇的新增用户接口,多添加几条数据(如新增test1、test2、test3……test10),确保分页测试有足够的数据支撑。

核心实操一:配置MyBatis-Plus分页插件(必配)

MyBatis-Plus的分页功能需要通过“分页插件”实现,零基础只需编写一个简单的配置类,就能开启分页功能,全程复制代码即可,无需理解复杂逻辑。

3.1 步骤1:创建配置类(MyBatisPlusConfig)

在com.example.springbootbasic包下,创建config包,编写MyBatisPlusConfig配置类,添加分页插件的配置,代码如下(直接复制即可):

package com.example.springbootbasic.config;import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;// @Configuration:标记当前类为配置类,让Spring容器识别@Configurationpublic class MyBatisPlusConfig {    // 配置分页插件(MyBatis-Plus 3.5+版本推荐写法)    @Bean    public MybatisPlusInterceptor mybatisPlusInterceptor() {        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();        // 添加分页插件,指定数据库类型(MySQL),避免分页适配异常        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(com.baomidou.mybatisplus.core.metadata.TableInfoHelper.DB_TYPE_MYSQL));        return interceptor;    }}

3.2 核心说明(零基础必懂)

1. @Configuration注解:标记当前类为Spring的配置类,相当于传统的XML配置文件,Spring Boot会自动扫描并加载该类中的配置;

2. MybatisPlusInterceptor:MyBatis-Plus的拦截器,用于添加分页、乐观锁等插件;

3. PaginationInnerInterceptor:分页插件核心类,指定数据库类型为MySQL(避免不同数据库分页语法差异导致的报错);

4. 配置注意:无需修改任何参数,复制上述代码,确保包路径正确,启动项目后,分页插件即可生效。

核心实操二:分页查询实操(零基础必练)

分页插件配置完成后,我们编写Service层和Controller层代码,调用MyBatis-Plus内置的分页方法,实现用户数据的分页查询,全程无需编写SQL,只需调用方法即可。

4.1 步骤1:Service层添加分页方法

打开UserService接口和UserServiceImpl实现类,添加分页查询方法。由于UserService继承了IService,IService已内置分页方法(page方法),我们无需编写实现逻辑,直接在Service接口中声明即可(规范写法)。

// UserService接口(新增分页方法声明)package com.example.springbootbasic.service;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.service.IService;import com.example.springbootbasic.entity.User;public interface UserService extends IService {    // 分页查询用户(参数:当前页码,每页显示条数)    IPage getUserPage(Integer pageNum, Integer pageSize);}
// UserServiceImpl实现类(实现分页方法)package com.example.springbootbasic.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.example.springbootbasic.entity.User;import com.example.springbootbasic.mapper.UserMapper;import com.example.springbootbasic.service.UserService;import org.springframework.stereotype.Service;@Servicepublic class UserServiceImpl extends ServiceImpl implements UserService {    // 实现分页查询方法    @Override    public IPage getUserPage(Integer pageNum, Integer pageSize) {        // 1. 创建分页对象,指定当前页码(pageNum)和每页显示条数(pageSize)        IPage page = new Page<>(pageNum, pageSize);        // 2. 调用IService的page方法,实现分页查询(无查询条件,查询所有数据并分页)        // 第一个参数:分页对象,第二个参数:查询条件(null表示无条件)        return this.page(page, null);    }}

4.2 步骤2:Controller层添加分页接口

打开UserController,添加分页查询接口,接收前端传递的“当前页码”和“每页显示条数”参数,调用Service层的分页方法,返回分页结果(包含分页信息和当前页数据)。

package com.example.springbootbasic.controller;import com.baomidou.mybatisplus.core.metadata.IPage;import com.example.springbootbasic.entity.User;import com.example.springbootbasic.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;    // 原有CRUD接口不变,新增分页查询接口    // 分页查询用户(GET请求,参数:pageNum=当前页码,pageSize=每页条数)    @GetMapping("/page")    public IPage getUserPage(            // @RequestParam:接收前端传递的参数,defaultValue表示默认值(避免参数为空报错)            @RequestParam(defaultValue = "1") Integer pageNum,            @RequestParam(defaultValue = "5") Integer pageSize) {        // 调用Service层的分页方法,返回分页结果        return userService.getUserPage(pageNum, pageSize);    }    // 以下为上一篇的CRUD接口,无需修改    @PostMapping("/add")    public String addUser(@RequestBody User user) {        boolean success = userService.save(user);        return success ? "新增用户成功" : "新增用户失败";    }    @GetMapping("/delete/{id}")    public String deleteUser(@PathVariable Integer id) {        boolean success = userService.removeById(id);        return success ? "删除用户成功" : "删除用户失败";    }    @PostMapping("/update")    public String updateUser(@RequestBody User user) {        boolean success = userService.updateById(user);        return success ? "修改用户成功" : "修改用户失败";    }    @GetMapping("/{id}")    public User getUserById(@PathVariable Integer id) {        return userService.getById(id);    }    @GetMapping("/list")    public List getAllUser() {        return userService.list();    }}

4.3 步骤3:启动项目,测试分页接口(零基础必做)

启动Spring Boot项目,确保启动成功(无报错),然后通过浏览器或Postman测试分页接口,验证分页效果,测试步骤如下:

测试:分页查询用户

请求地址:http://localhost:8080/user/page?pageNum=1&pageSize=5(pageNum=1表示第一页,pageSize=5表示每页显示5条)

测试结果:返回分页JSON数据,包含以下核心信息(零基础无需纠结细节,能看到分页效果即可):

1. total:总数据条数(如10条测试数据,total=10);

2. size:每页显示条数(5条);

3. current:当前页码(1);

4. records:当前页的数据列表(5条用户数据)。

修改请求参数测试:http://localhost:8080/user/page?pageNum=2&pageSize=5,会返回第6-10条数据,说明分页功能正常。

核心实操三:条件查询实操(零基础必练)

分页查询解决了“数据过多”的问题,而条件查询解决了“精准筛选”的问题。MyBatis-Plus提供了QueryWrapper类,用于构建查询条件,无需编写SQL,通过链式调用的方式,就能实现多条件组合查询,非常适合零基础入门。

5.1 核心条件查询API(零基础必记)

无需记忆所有API,重点掌握以下5个高频条件查询方法,就能应对基础开发中的大部分场景,结合示例理解,无需死记硬背:

1. eq:等于(如查询username等于test1的用户);

2. gt:大于(如查询age大于20的用户);

3. like:模糊查询(如查询email包含163.com的用户);

4. between:范围查询(如查询age在18-25之间的用户);

5. orderByAsc/orderByDesc:排序(如按age升序/降序排列)。

5.2 步骤1:Service层添加条件查询方法

打开UserService接口和UserServiceImpl实现类,添加2个常用的条件查询方法:① 按单个条件查询(如按年龄查询);② 按多条件组合查询(如按年龄+邮箱查询)。

数据库学习入门(Spring Boot入门:MyBatis-Plus进阶,搞定复杂数据库操作)

// UserService接口(新增条件查询方法声明)package com.example.springbootbasic.service;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.service.IService;import com.example.springbootbasic.entity.User;import java.util.List;public interface UserService extends IService {    // 分页查询用户    IPage getUserPage(Integer pageNum, Integer pageSize);    // 1. 单个条件查询:按年龄查询用户(查询age大于指定值的用户)    List getUserByAge(Integer age);    // 2. 多条件组合查询:按年龄+邮箱模糊查询    List getUserByAgeAndEmail(Integer age, String email);}
// UserServiceImpl实现类(实现条件查询方法)package com.example.springbootbasic.service.impl;import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;import com.baomidou.mybatisplus.core.metadata.IPage;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;import com.example.springbootbasic.entity.User;import com.example.springbootbasic.mapper.UserMapper;import com.example.springbootbasic.service.UserService;import org.springframework.stereotype.Service;import java.util.List;@Servicepublic class UserServiceImpl extends ServiceImpl implements UserService {    // 分页查询方法(不变)    @Override    public IPage getUserPage(Integer pageNum, Integer pageSize) {        IPage page = new Page<>(pageNum, pageSize);        return this.page(page, null);    }    // 1. 单个条件查询:按年龄查询(age大于指定值)    @Override    public List getUserByAge(Integer age) {        // 创建QueryWrapper对象,用于构建查询条件        QueryWrapper queryWrapper = new QueryWrapper<>();        // 构建条件:age > 指定年龄(gt表示大于)        queryWrapper.gt("age", age);        // 调用list方法,传入查询条件,返回符合条件的用户列表        return this.list(queryWrapper);    }    // 2. 多条件组合查询:按年龄+邮箱模糊查询    @Override    public List getUserByAgeAndEmail(Integer age, String email) {        QueryWrapper queryWrapper = new QueryWrapper<>();        // 条件1:age > 指定年龄        queryWrapper.gt("age", age);        // 条件2:email包含指定字符串(like表示模糊查询,%表示任意字符)        queryWrapper.like("email", email);        // 条件3:按age降序排列(可选,优化显示效果)        queryWrapper.orderByDesc("age");        // 返回符合条件的用户列表        return this.list(queryWrapper);    }}

5.3 步骤2:Controller层添加条件查询接口

打开UserController,添加2个条件查询接口,接收前端传递的查询条件参数,调用Service层的条件查询方法,返回查询结果。

package com.example.springbootbasic.controller;import com.baomidou.mybatisplus.core.metadata.IPage;import com.example.springbootbasic.entity.User;import com.example.springbootbasic.service.UserService;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.GetMapping;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import java.util.List;@RestController@RequestMapping("/user")public class UserController {    @Autowired    private UserService userService;    // 分页查询接口(不变)    @GetMapping("/page")    public IPage getUserPage(            @RequestParam(defaultValue = "1") Integer pageNum,            @RequestParam(defaultValue = "5") Integer pageSize) {        return userService.getUserPage(pageNum, pageSize);    }    // 新增条件查询接口1:按年龄查询(查询age大于指定值的用户)    @GetMapping("/byAge")    public List getUserByAge(@RequestParam Integer age) {        return userService.getUserByAge(age);    }    // 新增条件查询接口2:按年龄+邮箱模糊查询    @GetMapping("/byAgeAndEmail")    public List getUserByAgeAndEmail(            @RequestParam Integer age,            @RequestParam String email) {        return userService.getUserByAgeAndEmail(age, email);    }    // 原有CRUD接口(不变)    @PostMapping("/add")    public String addUser(@RequestBody User user) {        boolean success = userService.save(user);        return success ? "新增用户成功" : "新增用户失败";    }    @GetMapping("/delete/{id}")    public String deleteUser(@PathVariable Integer id) {        boolean success = userService.removeById(id);        return success ? "删除用户成功" : "删除用户失败";    }    @PostMapping("/update")    public String updateUser(@RequestBody User user) {        boolean success = userService.updateById(user);        return success ? "修改用户成功" : "修改用户失败";    }    @GetMapping("/{id}")    public User getUserById(@PathVariable Integer id) {        return userService.getById(id);    }    @GetMapping("/list")    public List getAllUser() {        return userService.list();    }}

5.4 步骤3:启动项目,测试条件查询接口(零基础必做)

启动Spring Boot项目,通过浏览器或Postman测试2个条件查询接口,验证条件查询效果,测试步骤如下:

测试1:按年龄查询(单个条件)

请求地址:http://localhost:8080/user/byAge?age=20(查询年龄大于20的用户)

测试结果:返回所有年龄大于20的用户列表,若测试数据中只有age=22、23的用户,会只返回这两条数据,说明条件查询正常。

测试2:按年龄+邮箱模糊查询(多条件)

请求地址:http://localhost:8080/user/byAgeAndEmail?age=18&email=163.com(查询年龄大于18、邮箱包含163.com的用户)

测试结果:返回符合两个条件的用户列表,且按年龄降序排列,说明多条件组合查询正常。

核心实操四:分页+条件查询综合实操(贴合实际开发)

在实际开发中,分页和条件查询往往是结合使用的(如“查询年龄大于20的用户,分页显示,每页5条”)。我们基于前面的代码,新增一个综合查询方法,实现“条件筛选+分页显示”,进一步贴合实际开发场景。

6.1 步骤1:Service层添加综合查询方法

// UserService接口(新增综合查询方法声明)public interface UserService extends IService {    // 分页查询用户    IPage getUserPage(Integer pageNum, Integer pageSize);    // 单个条件查询:按年龄查询    List getUserByAge(Integer age);    // 多条件组合查询:按年龄+邮箱模糊查询    List getUserByAgeAndEmail(Integer age, String email);    // 综合查询:条件+分页(查询age大于指定值的用户,分页显示)    IPage getUserPageByAge(Integer pageNum, Integer pageSize, Integer age);}
// UserServiceImpl实现类(实现综合查询方法)@Overridepublic IPage getUserPageByAge(Integer pageNum, Integer pageSize, Integer age) {    // 1. 创建分页对象    IPage page = new Page<>(pageNum, pageSize);    // 2. 创建查询条件    QueryWrapper queryWrapper = new QueryWrapper<>();    queryWrapper.gt("age", age); // 条件:age大于指定值    // 3. 调用page方法,结合分页和条件查询    return this.page(page, queryWrapper);}

6.2 步骤2:Controller层添加综合查询接口

// UserController新增综合查询接口@GetMapping("/pageByAge")public IPage getUserPageByAge(        @RequestParam(defaultValue = "1") Integer pageNum,        @RequestParam(defaultValue = "5") Integer pageSize,        @RequestParam Integer age) {    return userService.getUserPageByAge(pageNum, pageSize, age);}

6.3 步骤3:测试综合查询接口

请求地址:http://localhost:8080/user/pageByAge?pageNum=1&pageSize=5&age=18(查询年龄大于18的用户,第一页,每页5条)

测试结果:返回分页数据,且分页列表中只有年龄大于18的用户,说明“条件+分页”综合查询正常,完全贴合实际开发场景。

零基础必避坑:常见问题及解决方法

零基础学习者在实操分页和条件查询时,容易遇到以下4个常见问题,掌握解决方法,避免卡壳,高效完成学习:

7.1 坑点1:分页插件配置错误,分页失效

问题现象:调用分页接口,返回所有数据,没有分页效果(total等于records.size,current始终为1)。

解决方法:

1. 检查MyBatisPlusConfig配置类是否添加了@Configuration注解,确保Spring能扫描到;

2. 检查分页插件是否指定了数据库类型(MySQL),避免适配异常;

3. 检查分页方法是否使用了IPage和Page对象,确保调用的是MyBatis-Plus的page方法。

7.2 坑点2:条件查询无结果,或结果不符合预期

问题现象:调用条件查询接口,返回空列表,或返回的数据不符合查询条件。

解决方法:

1. 检查QueryWrapper构建的条件是否正确(如gt是大于,eq是等于,不要混淆);

2. 检查条件中的字段名称是否与数据库表字段一致(大小写敏感,如数据库字段是age,不要写成Age);

3. 检查前端传递的参数是否正确(如age参数是否为数字,email参数是否正确)。

7.3 坑点3:条件查询报错“column 'xxx' not found”

报错信息:Unknown column 'xxx' in 'where clause'(字段不存在)。

解决方法:检查QueryWrapper中指定的字段名称(如queryWrapper.gt("age", age)),确保与数据库表中的字段名称完全一致,不要写错字段名。

7.4 坑点4:分页参数为空,导致报错

报错信息:NullPointerException(空指针异常)。

解决方法:在Controller层的分页接口中,给pageNum和pageSize添加@RequestParam(defaultValue = "1")和@RequestParam(defaultValue = "5"),设置默认值,避免参数为空。

学习建议(零基础适配,稳步进阶)

本节是MyBatis-Plus的基础进阶内容,掌握分页和条件查询,就能应对大部分基础开发中的数据库查询场景,进一步夯实Spring Boot数据库开发基础,零基础学习者重点把握以下4点:

1. 重点实操,循序渐进:先掌握分页插件的配置和分页查询,再学习条件查询,最后结合两者实现综合查询,一步一个脚印,不要急于求成;

2. 理解核心用法,拒绝死记硬背:重点理解QueryWrapper的链式调用逻辑,记住5个高频条件查询API,结合实操示例,就能灵活运用,无需记忆所有API;

3. 结合实际场景练习:多尝试修改条件查询的逻辑(如新增between范围查询、eq等于查询),多测试分页参数(如pageNum=3、pageSize=10),加深对功能的理解;

4. 注重代码规范:保持“Entity→Mapper→Service→Controller”的分层写法,条件查询和分页查询的方法命名要规范(如getUserByAge、getUserPageByAge),为后续编写完整业务项目打下基础。

补充:后续我们将继续围绕“从基础到入门”的导向,基于本次的分页和条件查询,学习MyBatis-Plus的自定义SQL编写(应对复杂查询场景),同时结合前文的Redis、注解等知识点,编写一个完整的基础业务项目(如简单的用户管理系统),帮你逐步实现“能独立开发简单Spring Boot项目”的目标。

文章版权声明:除非注明,否则均为边学边练网络文章,版权归原作者所有

相关阅读