Mybatis Plus与SpringBoot的集成
1.引入Maven 依赖
提前创建好一个SpringBoot项目,然后在项目中引入MyBatis Plus依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.2</version>
</dependency>
完整的pom.xml
文件如下
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.0.9</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.atguigu</groupId>
<artifactId>hello-mp</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>hello-mp</name>
<description>hello-mp</description>
<properties>
<java.version>17</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.mysql</groupId>
<artifactId>mysql-connector-j</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.3.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
2.配置application.yml
文件
配置数据库相关内容如下
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: <password>
url: jdbc:mysql://host:post/database_name?useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2b8
3.创建实体类
创建与user
表相对应的实体类,如下
@Data
@TableName("user")
public class User {
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@TableField("name")
private String name;
@TableField("age")
private Integer age;
@TableField("email")
private String email;
}
知识点:
实体类中的三个注解的含义如下
-
@TableName
:表名注解,用于标识实体类所对应的表value
:用于声明表名
-
@TableId
:主键注解,用于标识主键字段value
:用于声明主键的字段名type
:用于声明主键的生成策略,常用的策略有AUTO
、ASSIGN_UUID
、INPUT
等等
-
@TableField
:普通字段注解,用于标识属性所对应的表字段value
:用于声明普通字段的字段名
4.分页插件
Mybatis-Plus提供了一个分页插件,使用它可以十分方便的完成分页查询。
- 配置分页插件
@Configuration
public class MPConfiguration {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
分页插件使用说明
-
构造分页对象
分页对象包含了分页的各项信息,其核心属性如下:
属性名 类型 默认值 描述 records List emptyList 查询数据列表 total Long 0 查询列表总记录数 size Long 10 每页显示条数,默认 10
current Long 1 当前页 分页对象既作为分页查询的参数,也作为分页查询的返回结果,当作为查询参数时,通常只需提供
current
和size
属性,如下IPage<T> page = new Page<>(current, size);
注:
IPage
为分页接口,Page
为IPage
接口的一个实现类。 -
分页查询
Mybatis Plus的
BaseMapper
和ServiceImpl
均提供了常用的分页查询的方法,例如:-
BaseMapper
的分页查询:IPage<T> selectPage(IPage<T> page,Wrapper<T> queryWrapper);
-
ServiceImpl
的分页查询:// 无条件分页查询 IPage<T> page(IPage<T> page); // 条件分页查询 IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
-
自定义Mapper
对于自定义SQL,也可以十分方便的完成分页查询,如下
Mapper
接口:IPage<UserVo> selectPageVo(IPage<?> page, Integer state);
Mapper.xml
:<select id="selectPageVo" resultType="xxx.xxx.xxx.UserVo"> SELECT id,name FROM user WHERE state=#{state} </select>
注意:
Mapper.xml
中的SQL只需实现查询list
的逻辑即可,无需关注分页的逻辑。5.逻辑删除功能
-
由于数据库中所有表均采用逻辑删除策略,所以查询数据时均需要增加过滤条件is_deleted=0
。
上述操作虽不难实现,但是每个查询接口都要考虑到,也显得有些繁琐。为简化上述操作,可以使用Mybatis-Plus提供的逻辑删除功能,它可以自动为查询操作增加is_deleted=0
过滤条件,并将删除操作转为更新语句。
-
步骤一:在
application.yml
中增加如下内容mybatis-plus: global-config: db-config: logic-delete-field: flag # 全局逻辑删除的实体字段名(配置后可以忽略不配置步骤二) logic-delete-value: 1 # 逻辑已删除值(默认为 1) logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)
-
步骤二:在实体类中的删除标识字段上增加
@TableLogic
注解@Data public class BaseEntity { @Schema(description = "主键") @TableId(value = "id", type = IdType.AUTO) private Long id; @Schema(description = "创建时间") @JsonIgnore private Date createTime; @Schema(description = "更新时间") @JsonIgnore private Date updateTime; @Schema(description = "逻辑删除") @JsonIgnore @TableLogic @TableField("is_deleted") private Byte isDeleted; }
注意:
逻辑删除功能只对Mybatis-Plus自动注入的sql起效,也就是说,对于手动在
Mapper.xml
文件配置的sql不会生效,需要单独考虑。
6.忽略特定字段
通常情况下接口响应的Json对象中并不需要create_time
、update_time
、is_deleted
等字段,这时只需在实体类中的相应字段添加@JsonIgnore
注解,该字段就会在序列化时被忽略。
具体配置如下
@Data
public class BaseEntity {
@Schema(description = "主键")
@TableId(value = "id", type = IdType.AUTO)
private Long id;
@Schema(description = "创建时间")
@JsonIgnore
@TableField(value = "create_time")
private Date createTime;
@Schema(description = "更新时间")
@JsonIgnore
@TableField(value = "update_time")
private Date updateTime;
@Schema(description = "逻辑删除")
@JsonIgnore
@TableField("is_deleted")
private Byte isDeleted;
}
7.自动填充
保存或更新数据时,前端通常不会传入isDeleted
、createTime
、updateTime
这三个字段,因此我们需要手动赋值。但是数据库中几乎每张表都有上述字段,所以手动去赋值就显得有些繁琐。为简化上述操作,我们可采取以下措施。
-
is_deleted
字段:可将数据库中该字段的默认值设置为0。 -
create_time
和update_time
:可使用mybatis-plus的自动填充功能,所谓自动填充,就是通过统一配置,在插入或更新数据时,自动为某些字段赋值,具体配置如下,详细信息可参考官方文档。-
为相关字段配置触发填充的时机,例如
create_time
需要在插入数据时填充,而update_time
需要在更新数据时填充。具体配置如下,观察@TableField
注解中的fill
属性。@Data public class BaseEntity { @Schema(description = "主键") @TableId(value = "id", type = IdType.AUTO) private Long id; @Schema(description = "创建时间") @JsonIgnore @TableField(value = "create_time", fill = FieldFill.INSERT) private Date createTime; @Schema(description = "更新时间") @JsonIgnore @TableField(value = "update_time", fill = FieldFill.UPDATE) private Date updateTime; @Schema(description = "逻辑删除") @JsonIgnore @TableLogic @TableField("is_deleted") private Byte isDeleted; }
-
配置自动填充的内容,具体配置如下
-
@Component
public class MybatisMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
this.strictInsertFill(metaObject, "createTime", Date.class, new Date());
}
@Override
public void updateFill(MetaObject metaObject) {
this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());
}
}