MyBatis-Plus备忘笔记

依赖

使用SpringBoot时在Maven添加Starter:

1
2
3
4
5
6
7
8
9
10
11
12
13
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-boot-starter -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency>
<!-- 这个Generator根据需要添加 -->
<!-- https://mvnrepository.com/artifact/com.baomidou/mybatis-plus-generator -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.3</version>
</dependency>

配置

与在SpringBoot中使用Mybatis一样,在application配置文件中配置数据源即可。

1
2
3
4
5
6
7
8
9
10
11
12
spring:
datasource:
# MySQL 8
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 114514
url: jdbc:mysql://localhost:3306/tutorial

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

Mapper

声明Mapper接口并继承MyBatisPlus中的BaseMapper<Entity>:

1
public interface MyMapper extends BaseMapper<My>{...}

这里My为这个Mapper主要操作的实体类。

然后在你@SpringBootApplication注解的启动类加上@MapperScan(“mapper包根目录”)

脱裤子放屁,只需要在Mapper接口上写上@Mapper注解就行了。

BaseMapper提供许多简单的、便利的操作功能。

Service

MybatisPlus的偷懒魔爪伸到了业务层,但实际上和Mapper的操作差不多。

1
public class MyServiceImpl extends ServiceImpl<MyMapper,My> implements MyServiceIntf{...}

实体

实体和往常一样创建一个POJO类就行,但MybatisPlus提供了一些注解。

不要使用基本类型!

  • TableName

对实体类,默认是类名与表名完全对应(驼峰与下划线自动转换),当不对应是需要指定实体对应表名。

1
2
@TableName("normal_table")
public class MySuperObject{...}
  • TableId

与上述类似,当主键名称不对应可以指示(第一个参数value)。

第二个参数Type设置这个主键的生成策略,常用的有以下:

策略 效果
IdType.NONE 默认,如果主键为空也不管,和往常一样引发异常
IdType.AUTO 当数据库设置了主键自增,那么会自己填写自增后的ID;如果数据库中没有设置,同NONE
IdType.ASSIGN_ID 不管数据库有没有设置自增,如果为空都根据雪花算法生成一个ID
1
2
3
4
@TableId("normal_id",IdType.ASSIGN_ID)
private Long superId;
//数据库中为normal_id而代码实体类为superId,
//想要生成正经的ID应该使用Long,数据库使用BIGINT。
  • TableField

与TableID基本一致,就是不用于主键。

  • TableLogic

启用逻辑删除。

在实体类某个属性(数据库表中也要有)添加,启用逻辑删除,此时Mybatis的各种操作只是将行数据(的那个属性)设置为已删除而不物理上地删除。

1
2
@TableLogic
private Integer isDeleted;

另外可以指定什么值代表已删除。

@TableLogic("未删除值","已删除值")

条件构造器

备忘录解释那么多干什么,看官网文档

其实就是类似于某些ORM框架,把SQL转化为有类型的、链式的方法调用,如query.like(My::Name, "江").gt(My::Age, 96)

条件构造器按如何区分字段可分为XxxWrapper和LambdaXxxWrapper(上面的例子就是),按可以进行的操作可以分为QueryWrapper和UpdateWrapper。尽量使用LambdaXxxWrapper。

如果Mapper是继承了BaseMapper的话,他都会有使用条件构造器的方法,简单使用如下:

1
2
3
4
5
6
7
...
QueryWrapper<My> wp = new QueryWrapper<>();
wp.like(My::getName, "江")
.gt(My::getAge, 96)
.orderByAsc(My::getAge);
myMapper.selectList(wp);
...

使用QueryWrapper也可以修改:

1
2
3
4
5
6
7
8
9
10
My newMy = new My();
...
//设置newMy的变化属性

QueryWrapper<My> wp = new QueryWrapper<>();
wp.like(My::getName, "江")
.gt(My::getAge, 96)
.orderByAsc(My::getAge);

myMapper.update(newMy, wp);

但修改的正统方法是通过UpdateWrapper:

1
2
3
4
5
6
7
8
UpdateWrapper<My> wp = new UpdateWrapper<>();
wp.like(My::getName, "江")
.gt(My::getAge, 96)
.orderByAsc(My::getAge)
.set(My::getAge, 95)
.set()
...
myMapper.update(null, wp);

子查询可以通过.inSql().notInSql()方法判断是否在子查询集合。

需要根据条件开关Wrapper某个小条件,注意到condition参数。

自带的分页插件

MybatisPlus的插件的添加方法都是通过配置类(本文是SpringBoot!):

1
2
3
4
5
6
7
8
9
10
//这段代码添加的就是分页插件!
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.你的数据库类型));
return interceptor;
}
}

使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//定义Page实体,决定范围,类似但不同于limit ?,?
Page<My> toPage = new Page<>(从1起的页数不是INDEX, 每页多少条);
// 设置查询条件
QueryWrapper<My> wrapper = new QueryWrapper<>();
wrapper.like(My::getName, "江");
// 执行查询,用IPage来接收
IPage<My> iPage = myMapper.selectPage(toPage, wrapper);
//实际上你后面直接用toPage也可以!
// 查看分页信息
System.out.println("当前页:" + iPage.getCurrent());
System.out.println("总页数:" + iPage.getPages());
System.out.println("每一页显示的条数:" + iPage.getSize());
System.out.println("总条数:" + iPage.getTotal());
// 分页后的数据列表
return iPage.getRecords();

自定义查询中也可以使用这个分页插件,只需要第一个参数为Page,SQL中不需要写limit之类的。


MyBatis-Plus备忘笔记
https://sodacooky.netlify.app/2022/MyBatis-Plus备忘笔记/
作者
Sodacooky
发布于
2022年10月19日
许可协议