前言
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。(官网)
SpringBoot项目整合MyBatisPlus学习笔记
快速入门
添加依赖
mybatis-plus-boot-starter
依赖中包含了mybatis-spring
的依赖,所以不需要重复添加MyBatis的依赖。如果重复添加,并且版本不相同,会有问题
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency>
<dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency>
<dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency>
|
添加配置
src/main/resources/application.yml
1 2 3 4 5 6
| spring: datasource: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql:/// username: password:
|
创建实体类
src/main/java/com/pojo/User.java
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 26 27 28 29 30 31
| package com.pojo;
public class User {
private int id; private String name;
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
@Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + '}'; } }
|
持久层
使用Mapper注解定义bean
src/main/java/com/dao/UserDao.java
1 2 3 4 5 6 7 8 9
| package com.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.pojo.User; import org.apache.ibatis.annotations.Mapper;
@Mapper public interface UserDao extends BaseMapper<User> { }
|
使用MapperScan方式扫描bean
- 不使用Mapper注解,而是在主启动类添加
@MapperScan
注解,实现Mapper的扫描
com.dao
:指定扫描的包
直接使用MyBatisPlus封装好的CRUD方法
src/test/java/com/dao/UserDaoTests.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.dao;
import com.pojo.User; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest;
@SpringBootTest public class UserDaoTests {
@Autowired private UserDao userDao;
@Test public void test() { System.out.println(userDao.selectList(null)); } }
|
使用MyBatisPlus实现CRUD增删改查操作
创建条件对象
- 所有需要传递条件的操作都需要先创建条件对象,然后将条件作为参数传入
QueryWrapper类型的条件
字符串传值
1 2
| QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("字段名", 值);
|
设置查询投影
1
| queryWrapper.select("id", "name");
|
重载方法
- 第一个参数为true时生效,第一个参数为false时无效
1
| queryWrapper.eq(true, "字段名", 值);
|
Lambda表达式传值
1 2
| QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(User::getId, 值);
|
LambdaQueryWrapper类型
Lambda表达式传值
1 2
| LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>(); queryWrapper.eq(User::getId, 值);
|
重载方法
- 第一个参数为true时生效,第一个参数为false时无效
1
| queryWrapper.eq(true, User::getId, 值);
|
设置查询投影
1
| queryWrapper.select(User::getId, User::getName);
|
查询条件方法
- 主要针对于查询操作的条件。需要先创建条件对象,再在条件对象中添加查询条件
- 字段名传值时,既可以使用字符串方式,也可以使用Lambda表达式方式
范围匹配
区间
1
| queryWrapper.between("字段名", 最小值, 最大值);
|
相等
1
| queryWrapper.eq("字段名", 值);
|
大于
1
| queryWrapper.gt("字段名", 值);
|
小于
1
| queryWrapper.lt("字段名", 值);
|
大于等于
1
| queryWrapper.ge("字段名", 值);
|
小于等于
1
| queryWrapper.le("字段名", 值);
|
多条件范围
并且条件
1 2
| LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.ge(User::getId, 1).le(User::getId, 1);
|
或者条件
1 2
| LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>(); lambdaQueryWrapper.le(User::getId, 1).or().ge(User::getId, 1);
|
模糊匹配
从任意位置匹配
1
| queryWrapper.like("字段名", "关键字");
|
从左侧匹配
1
| queryWrapper.likeLeft("字段名", "关键字");
|
从右侧匹配
1
| queryWrapper.likeRight("字段名", "关键字");
|
分组
<group>
:指定分组的字段名
1 2
| queryWrapper.select("COUNT(*), <group>"); queryWrapper.groupBy("<group>");
|
新增
1
| userDao.insert(new User());
|
删除
根据id删除数据
<id>
:需要删除的id
1
| userDao.deleteById(<id>);
|
根据多个id删除数据
1 2 3 4
| ArrayList<Integer> list = new ArrayList<>(); list.add(<id>); list.add(<id>); userMapper.deleteBatchIds(list);
|
根据条件对象删除数据
1
| userMapper.delete(queryWrapper);
|
修改
根据id修改数据
<id>
:id
<name_new>
:修改后的字段值
1 2 3 4
| User user = new User(); user.setId(<id>); user.setName(<name_new>); userDao.updateById(user);
|
查询
根据id查询数据
根据多个id查询数据
1 2 3 4
| ArrayList<Integer> list = new ArrayList<>(); list.add(<id>); list.add(<id>); userMapper.selectBatchIds(list);
|
根据条件查询数据
1
| userDao.selectList(new User());
|
根据条件对象查询数据
1
| userDao.selectList(queryWrapper);
|
1
| userDao.selectList(null);
|
根据条件对象查询数据并重新封装
- 根据条件对象查询数据,将查询结果封装为List<Map<>>
1
| List<Map<String, Object>> maps = userDao.selectMaps(queryWrapper);
|
1
| List<Map<String, Object>> maps = userDao.selectMaps(null);
|
查询个数
根据条件对象查询个数
1
| userMapper.selectCount(queryWrapper);
|
查询所有数据个数
1
| userMapper.selectCount(null);
|
数据表与字段的映射关系配置
实体类添加注解
- 默认实体类的类名要与数据表的表名首字母大写后相同
- 默认实体类的属性名要与数据表的字段名相同
@TableName("数据表名")
:指定数据表的配置,指定映射的数据表名
@TableId()
:指定主键的配置
type = IdType.AUTO
:指定主键自增策略的配置
IdType.NONE
:缺省值,无策略
IdType.INPUT
:自己手动指定
IdType.AUTO
:主键自增
IdType.ASSIGN_UUID
、IdType.UUID
:通过UUID生成
IdType.ASSIGN_ID
、IdType.ID_WORKED
、IdType.ID_WORKED_STR
:通过雪花算法生成
value = "字段名"
:指定在数据表中映射的字段名
@TableField()
:指定字段配置
value = "字段名"
:指定在数据表中映射的字段名
exist = false
:指定此属性与数据表中的字段映射是否存在
true
:缺省值,此属性与数据表中的字段映射存在
false
:此属性与数据表中的字段映射不存在
select = false
:指定此属性是否作为SQL查询语句的查询结果
true
:缺省值,此属性作为SQL查询语句的查询结果
false
:此属性不作为SQL查询语句的查询结果
src/main/java/pojo/User.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| @TableName("user") public class User {
@TableId(type = IdType.AUTO, value = "id") private Integer id;
@TableField(value = "name") private String name; @TableField(select = false) private String password; @TableField(exist = false) private String type; }
|
分页查询
创建拦截器配置类
- 创建一个MyBatisPlus拦截器bean,在MyBatisPlus拦截器中添加MyBatisPlus分页拦截器
src/main/java/com/conf/MyBatisPlusConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.conf;
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 public class MyBatisPlusConfig {
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return mybatisPlusInterceptor; } }
|
创建分页对象
1 2
| IPage iPage = new Page(指定页码, 指定当前页的数据); userDao.selectPage(iPage, null);
|
iPage.getPages()
:获取一共多少页
iPage.getTotal()
:获取一共多少条数据
iPage.getCurrent()
:获取当前页码值
iPage.getSize()
:获取每页多少条数据
iPage.getRecords()
:当前页的所有数据
逻辑删除
- 在数据表中指定一个字段
deleted
,用于逻辑删除
- 如果SQL查询语句如果有逻辑删除字段,每个SQL语句末尾会追加
WHERE deleted=0
- 如果SQL删除语句如果有逻辑删除字段,那么删除操作改为修改逻辑删除字段的操作
实体类添加字段
@TableLogic()
:指定逻辑删除字段
value = ""
:指定没有被删除的逻辑值
delval = ""
:指定被删除的逻辑值
1 2 3 4 5
| public class User { @TableLogic(value = "0", delval = "1") private Integer deleted; }
|
乐观锁(修改操作并发处理)
- 如果请求的并发量在2000以内,可以采用乐观锁的方式解决高并发
- 在数据表中指定一个字段
version
,用于定义版本
- 当执行修改SQL语句时如果有版本字段,那么除了修改业务字段,还会将版本字段自增1,表示版本修改,同时会在末尾追加
WHERE version=版本号
创建拦截器配置类
src/main/java/com/conf/MyBatisPlusConfig.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| package com.conf;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration;
@Configuration public class MyBatisPlusConfig {
@Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor(); mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); return mybatisPlusInterceptor; } }
|
实体类添加字段
@Version
:指定乐观锁字段
src/main/java/pojo/User.java
1 2 3 4 5
| public class User { @Version private Integer version; }
|
在执行修改SQL语句时添加版本号
- 通过id,执行查询语句,得到旧的版本号
- 修改内容
- 执行修改时,将版本号和修改后的内容一并传递
<id>
:id
<name_new>
:修改后的名称
<version>
:版本号
1 2 3 4 5 6
| User user = userDao.selectById(<id>);
user.setName(<name_new>);
userDao.updateById(user);
|
其他配置
MyBatisPlus开启控制台的日志
src/main/resources/application.yml
1 2 3
| mybatis-plus: configuration: log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
|
清除MyBatisPlus Banner
1 2 3
| mybatis-plus: global-config: banner: false
|
指定xml的mapper文件扫描路径
1 2
| mybatis-plus: mapper-locations: classpath:/mappers/*.xml
|
开启驼峰命名映射
- 数据库的字段可能会采用
_
的方式连接多个单词作为字段名
- Java中通常使用驼峰命名法为类的属性命名
- 开启驼峰命名映射后,类的属性名与数据库的字段名映射关系,从原本的
xxXx=>xxXx
,改为xxX=>xxx_xx
1 2 3
| mybatis-plus: configuration: map-underscore-to-camel-case: true
|
设置主键映射的默认的自增策略
none
:缺省值,无策略
input
:自己手动指定
auto
:主键自增
assign_uuid
、uuid
:通过UUID生成
assign_id
、id_worker
、id_worker_str
通过雪花算法生成
1 2 3 4
| mybatis-plus: global-config: db-config: id-type: assign_uuid
|
设置表名映射时的表名前缀
1 2 3 4
| mybatis-plus: global-config: db-config: table-prefix: t_
|
设置逻辑删除字段的配置
指定逻辑删除字段的字段名
1 2 3 4
| mybatis-plus: global-config: db-config: logic-delete-field: deleted
|
指定没有被删除的逻辑值
1 2 3 4
| mybatis-plus: global-config: db-config: logic-not-delete-value: 0
|
指定被删除的逻辑值
1 2 3 4
| mybatis-plus: global-config: db-config: logic-delete-value: 1
|
代码生成器
引入依赖
pom.xml
1 2 3 4 5 6 7 8 9 10 11 12 13
| <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-generator</artifactId> <version>3.4.1</version> </dependency>
<dependency> <groupId>org.apache.velocity</groupId> <artifactId>velocity-engine-core</artifactId> <version>2.3</version> </dependency>
|
创建生成器类
src/main/java/com/Generator.java
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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| package com;
import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.generator.AutoGenerator; import com.baomidou.mybatisplus.generator.config.DataSourceConfig; import com.baomidou.mybatisplus.generator.config.GlobalConfig; import com.baomidou.mybatisplus.generator.config.PackageConfig; import com.baomidou.mybatisplus.generator.config.StrategyConfig;
public class Generator { public static void main(String[] args) { AutoGenerator autoGenerator = new AutoGenerator();
DataSourceConfig dataSourceConfig = new DataSourceConfig(); dataSourceConfig.setDriverName("com.mysql.cj.jdbc.Driver"); dataSourceConfig.setUrl("jdbc:mysql:///"); dataSourceConfig.setUsername(""); dataSourceConfig.setPassword(""); autoGenerator.setDataSource(dataSourceConfig);
GlobalConfig globalConfig = new GlobalConfig(); globalConfig.setOutputDir(""); globalConfig.setOpen(false); globalConfig.setAuthor("作者"); globalConfig.setFileOverride(true); globalConfig.setMapperName("%sDao"); globalConfig.setIdType(IdType.ASSIGN_ID); autoGenerator.setGlobalConfig(globalConfig);
PackageConfig packageConfig = new PackageConfig(); packageConfig.setParent("com"); packageConfig.setEntity("pojo"); packageConfig.setMapper("dao"); autoGenerator.setPackageInfo(packageConfig);
StrategyConfig strategyConfig = new StrategyConfig(); strategyConfig.setTablePrefix("t_"); strategyConfig.setEntityLombokModel(true); strategyConfig.setRestControllerStyle(true); strategyConfig.setLogicDeleteFieldName("deleted"); strategyConfig.setVersionFieldName("version"); autoGenerator.setStrategy(strategyConfig);
autoGenerator.execute(); } }
|
完成
参考文献
哔哩哔哩——黑马程序员