目录
1.首先就是正常的创建一个项目,然后选好要用的配置依赖,只需要选择MySQL,这里我们找不到MybatisPlus的依赖,因为没有别idea收录。
2.我们手动的pom文件中加入MybatisPlus的依赖,刷新。
前言:前面我们学了很多的框架,这里我们要学习一个更简单,基于Mybatis框架基础上提出来的MybatisPlus框架,看看他是如何提高开发效率的以及具体的实现方式。
MyBatisPlus概述
MyBatisPlus(简称MP)是基于MyBatis框架基础上开发的增强型工具,旨在简化开发、提高效率
官网:https://mybatis.plus/ https://mp.baomidou.com/
MybatisPlus入门案例:
我们通过MybatisPlus的入门案例,快速的了解MybatisPlus框架的使用和流程。
1.首先就是正常的创建一个项目,然后选好要用的配置依赖,只需要选择MySQL,这里我们找不到MybatisPlus的依赖,因为没有别idea收录。
2.我们手动的pom文件中加入MybatisPlus的依赖,刷新。
<dependency>
<groupId>com.baomidou</groupId>I<artifactId>mybatis-plus-boot-starter</artifactId><version>3.4.1</version>
</dependency>
也可以顺便加上一个druid依赖,数据库连接池组件,管理数据库连接
<dependency>
<groupId>com.alibabak/groupId><artifactId>druid</artifactId><version>1.1.16</version></dependency>
3.配置yml配置文件
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSourcedriver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatisplus_db?serverTimezone=UTCusername: root
password: 123456
4.先创建一个实体类user用于封装数据
这里我们介绍一个好用的工具++lombok++
<dependency>
<groupId>org.projectlombokk/groupId><artifactId>lombok</artifactId></dependency>
然后在实体类上加上**@Data**注解,这样就不用写对应setter,getter等方法。
5.创建数据层接口UserDao
@Mapper
public interface UserDaoextends BaseMapper<User>
6.测试类中
注入对应的接口对象,Mapepr创建的代理对象,我们可以在里面直接调用BaseMapper提供好的方法,进行增删改查。
MyBatisPlus特性
无侵入:只做增强不做改变,不会对现有工程产生影响
强大的CRUD操作:内置通用 Mapper,少量配置即可实现单表CRUD
操作支持Lambda:编写查询条件
无需担心字段写错
支持主键自动生成
内置分页插件
标准数据层开发:
|--------|------------------------------------------|
| 功能 | 自定义接口 |
| 新增 | boolean save(T t) |
| 删除 | boolean delete(int id) |
| 修改 | boolean update(T t) |
| 根据id查询 | T getById (int id) |
| 查询全部 | List<T> getAll() |
| 分页查询 | PageInfo<T> getAll(int page, int size) |
| 按条件查询 | List<T> getAll(Condition condition) |
这些方法全是继承于BaseMapper中的。
MybatisPlus的分页查询:
1.设置分页拦截器作为Spring管理bean。
拦截器的作用就是++自动改写sql语句,++自动的加上分页功能,除此之外,还可以
|--------------------------|
| SQL改写 - 自动添加分页语法 |
| 方言适配 - 支持所有数据库 |
| 自动COUNT - 无需手动查询总记录数 |
| 性能优化 - 优化COUNT查询 |
| 统一处理 - 所有分页方法自动生效 |
@Configuration
public class MpCongfig {
@Bean
public MybatisPlusInterceptor pageInterceptor(){MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterdeptor(new PaginationInnerInterceptor());return interceptor;}
2.在test中执行分页查询:
IPage page = new Page(2,3);
userDao.selectPage(page, null);System.out.println("当前页码:"+page.getCurrent());System.out.println("每页数据总量:"+page.getSize());System.out.println("总页数:"+page.getPages());System.out.println("数据总量:"+page.getTotal());System.out.println("当前页数据:"+page.getRecords());
3.为了看到查询的结果,开启了日志

DQL编程控制:
条件查询一设置查询条件
格式三:lambda格式(推荐)
QueryWrapper<User> qw = new QueryWrapper<User>();/查询年龄大于等于18岁,小于65岁的用户qw.lambda().lt(User::getAge,65).ge(User::getAge,18);List<User> userList = userDao.selectList(qw);System.out.println(userList);
格式四:lambda格式(推荐)
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();/查询年龄大于等于18岁,小于65岁的用户lqw.lt(User::getAge,65).ge(User::getAge,18);List<User> userList = userDao.selectList(lqw);System.out.println(userList);
这里使用了方法引用,这是JDK8的新特性,更加的简化了书写,关于匿名内部类,形象的说就是一个临时的类,通常是写在方法的参数中。
| 场景 | 推荐方式 | 原因 |
|---|---|---|
| 逻辑简单,只用一次 | Lambda | 简洁明了 |
| 逻辑复杂(多行) | Lambda + 代码块 | user -> { ...多行代码... } |
| 直接调用现有方法 | 方法引用 | 最简洁 |
| 需要实现多个方法 | 匿名内部类 | Lambda只能实现一个方法 |
| 需要this引用 | 匿名内部类 | Lambda的this指向不同 |
| 老版本Java(<8) | 匿名内部类 | 不支持Lambda |
MyBatis-Plus中的实际应用
// 匿名内部类方式(老写法)
QueryWrapper<User> qw = new QueryWrapper<>();
qw.lambda().lt(new SFunction<User, Integer>() {
@Override
public Integer apply(User user) {
return user.getAge();
}
}, 10);
// Lambda表达式(简化写法)
QueryWrapper<User> qw = new QueryWrapper<>();
qw.lambda().lt(user -> user.getAge(), 10);
// 方法引用(最简洁)
QueryWrapper<User> qw = new QueryWrapper<>();
qw.lambda().lt(User::getAge, 10); // 就是基于Lambda的进一步简化
条件查询------null值处理:
条件参数控制
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();lqw.ge(null != userQuery.getAge(),User::getAge, userQuery.getAge());lqw.lt(null != userQuery.getAge2(),User::getAge, userQuery.getAge2());List<User> userList = userDao.selectList(lqw);System.out.println(userList);
条件参数控制(链式编程)
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();lqw.ge(null != userQuery.getAge(),User::getAge, userQuery.getAge()).lt(null != userQuery.getAge2(),User::getAge, userQuery.getAge2());List<User> userList = userDao.selectList(lqw);System.out.println(userList);
解释基础知识:
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper
作用:创建一个用于构建Lambda条件查询的包装器对象
List<User> userList = userDao.selectList(lqw);
| 部分 | 说明 | 比喻 |
|---|---|---|
List<User> |
返回类型:User对象的列表 | 结果是个名单 |
userList |
变量名,存储查询结果 | 把名单放在这个盒子里 |
= |
赋值 | 把查询结果装进变量 |
userDao |
数据访问对象 | 负责取数据的专员 |
.selectList |
查询多个记录的方法 | 去数据库"拿一批数据" |
(lqw) |
传入查询条件 | 告诉专员"按这些条件找" |
查询投影:(可以用于分组统计)
查询结果包含模型类中部分属性(实体类内部的属性)
LambdaQueryWrapper<User> lqw = new LambdaQueryWrapper<User>();lqw.select(User::getId,User::getName,User::getAge);List<User> userList = userDao.selectList(lqw);System.out.println(userlist);
查询结果包含模型类中未定义的属性
QueryWrapper<User> qm = new QueryWrapper<User>();qm.select("count(*) as nums,gender");qm.groupBy("gender");List<Map<String, Object>> maps= userDao.selectMaps(qm);System.out.println(maps);
| 对比项 | 第一种(模型类属性) | 第二种(未定义属性) |
|---|---|---|
| 使用的Wrapper | LambdaQueryWrapper |
QueryWrapper |
| 查询方法 | selectList |
selectMaps |
| 返回类型 | List<User> |
List<Map<String, Object>> |
| 返回结构 | 实体类对象 | 键值对Map |
| 字段来源 | User类中已定义 | 可以是任意计算结果 |
| 典型场景 | 列表页显示 | 统计报表 |
| 类型安全 | ✅ 编译期检查 | ❌ 运行时才知道 |
| 灵活性 | 低(只能取现有字段) | 高(可以计算新字段) |
| 功能 | QueryWrapper | LambdaQueryWrapper | 说明 |
|---|---|---|---|
| 等值查询 | eq("name", "张三") |
eq(User::getName, "张三") |
Lambda有类型检查 |
| 模糊查询 | like("name", "张") |
like(User::getName, "张") |
同上 |
| 范围查询 | between("age", 18, 30) |
between(User::getAge, 18, 30) |
同上 |
| 聚合函数 | select("count(*)") |
❌ 不支持 | QueryWrapper更灵活 |
| 分组 | groupBy("dept_id") |
❌ 不支持 | QueryWrapper更灵活 |
| 连表查询 | 支持字符串 | ❌ 不支持 | QueryWrapper更灵活 |
| 自定义字段 | select("concat(name,age)") |
❌ 不支持 | QueryWrapper更灵活 |
条件方法速查表:
| 分类 | 方法 | 说明 | 示例 |
|---|---|---|---|
| 等于 | eq |
= | eq(User::getName, "张三") |
| 不等于 | ne |
!= | ne(User::getName, "张三") |
| 大于 | gt |
> | gt(User::getAge, 18) |
| 大于等于 | ge |
>= | ge(User::getAge, 18) |
| 小于 | lt |
< | lt(User::getAge, 60) |
| 小于等于 | le |
<= | le(User::getAge, 60) |
| 之间 | between |
BETWEEN | between(User::getAge, 20, 30) |
| 不在之间 | notBetween |
NOT BETWEEN | notBetween(User::getAge, 20, 30) |
| 在集合中 | in |
IN | in(User::getAge, 18,20,25) |
| 不在集合中 | notIn |
NOT IN | notIn(User::getAge, 18,20,25) |
| 模糊包含 | like |
LIKE '%值%' | like(User::getName, "张") |
| 以...开头 | likeRight |
LIKE '值%' | likeRight(User::getName, "张") |
| 以...结尾 | likeLeft |
LIKE '%值' | likeLeft(User::getName, "张") |
| 不包含 | notLike |
NOT LIKE | notLike(User::getName, "张") |
| 为空 | isNull |
IS NULL | isNull(User::getEmail) |
| 不为空 | isNotNull |
IS NOT NULL | isNotNull(User::getEmail) |
| 升序 | orderByAsc |
ORDER BY ASC | orderByAsc(User::getAge) |
| 降序 | orderByDesc |
ORDER BY DESC | orderByDesc(User::getCreateTime) |