前言
MyBatis-Plus是在MyBatis基础上的一个增强工具库,旨在简化开发者的工作,提高开发效率,同时保留MyBatis的灵活性。使用 MyBatis-Plus 可以减少重复性的代码,简化常见的数据库操作
官方学习文档:MyBatis-Plus (baomidou.com)
一.Mybatis-plus介绍
1.Mybatis-plus特性
-
CRUD操作的增强:
Mybatis-Plus
通过提供通用的Mapper接口和封装的CRUD方法,简化了数据库的增删改查操作。开发者可以通过继承通用Mapper接口,无需编写SQL语句,就能完成基本的CRUD操作。 -
条件构造器:
Mybatis-Plus
提供了强大的条件构造器,使得构建复杂的查询条件变得更加灵活和易于维护。条件构造器支持链式调用,可以根据需求动态添加查询条件,包括等值条件、范围条件、模糊查询等。 -
自动分页:
Mybatis-Plus
可以自动处理分页查询,开发者只需要在查询方法中添加分页参数,即可实现数据的分页查询。它支持多种数据库的分页方式,如MySQL
的LIMIT语句、Oracle的ROWNUM
等。 -
代码生成器:
Mybatis-Plus
提供了一个代码生成器,可以根据数据库表结构自动生成实体类、Mapper接口、XML映射文件等基本代码。开发者可以通过简单的配置,快速生成大量的基础代码,减少了手写重复代码的工作量。 -
全局通用操作:
Mybatis-Plus
还提供了一些全局通用操作的增强,如逻辑删除、字段自动填充、乐观锁等。这些功能可以通过注解或配置进行开启,并且可以自定义实现,以满足不同业务场景的需求。
小结:
Mybatis-Plus
简化了Mybatis
的开发流程,提高了开发效率。它提供了一些常用功能的增强,使得开发者无需编写繁琐的SQL语句,即可完成常见的数据库操作。同时,它也提供了一些附加功能,如条件构造器、自动分页、代码生成器等,进一步提升了开发效率和代码质量。
2.Mybatis-plus结构
核心模块:MyBatis-Plus Core: 包含了 MyBatis-Plus 的核心功能,如通用 Mapper 接口、条件构造器、分页插件等。
通用 Mapper 接口:MyBatis-Plus 提供了一组通用的 Mapper 接口,最常用的是 BaseMapper
接口。通过继承这些通用 Mapper 接口,可以直接使用通用的 CRUD 操作方法,无需手动编写对应的 SQL 语句。
条件构造器:MyBatis-Plus 的条件构造器提供了一种链式调用的方式来构建查询条件,以便更方便地生成动态 SQL 语句。
分页插件:MyBatis-Plus 内置了用于分页查询的插件,通过 Page
类和相关的方法,可以更方便地进行分页操作。
自动填充功能:MyBatis-Plus 提供了自动填充功能,通过注解实现在插入或更新操作时自动填充指定字段的值。
逻辑删除和乐观锁支持:MyBatis-Plus 提供了注解和相应的功能,用于方便地实现逻辑删除和乐观锁。
全局配置:MyBatis-Plus 支持更多的全局配置选项,包括性能分析、SQL 执行器类型、缓存等方面的配置。
代码生成器:MyBatis-Plus 提供了代码生成器,可以根据数据库表结构自动生成实体类、Mapper 接口、Service 类等代码,加速开发过程。
性能分析功能:MyBatis-Plus 集成了性能分析功能,方便开发者监控 SQL 执行性能。
其他工具和扩展:MyBatis-Plus 还提供了其他一些工具和扩展,如条件查询 Wrapper 类、枚举处理器、元对象(MetaObject)等,以增强 MyBatis 的功能和灵活性。
小结:这些组件和功能共同构成了 MyBatis-Plus 的结构,使开发者能够更轻松地进行数据库操作,同时提高代码的可维护性和可读性。在使用 MyBatis-Plus 时,通常需要引入相应的依赖,配置相应的参数,然后即可在项目中享受到 MyBatis-Plus 提供的便利功能。
二.Mybatis-plus入门
1.集成SpringBoot导入依赖
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.2</version>
</dependency><dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.5.2</version>
</dependency><dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
2. 配置application.yml文件
server:
port: 8080
Spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
username: root
password: 123456
url: jdbc:mysql://localhost:3306/bookshop
mybatis-plus:
# 类型别名
type-aliases-package: com.yu.boot.entity
configuration:
# 驼峰命名
map-underscore-to-camel-case: true
3.创建生成器文件
package com.yu.mybatis_plus.config;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.DataSourceConfig;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
@Slf4j
public class MySQLGenerator {
private final static String URL = "jdbc:mysql://localhost:3306/bookshop";
private final static String USERNAME = "root";
private final static String PASSWORD = "123456";
private final static DataSourceConfig.Builder DATA_SOURCE_CONFIG =
new DataSourceConfig.Builder(URL, USERNAME, PASSWORD);
public static void main(String[] args) {
FastAutoGenerator.create(DATA_SOURCE_CONFIG)
.globalConfig(
(scanner, builder) ->
builder.author(scanner.apply("请输入作者名称?"))
.outputDir(System.getProperty("user.dir") + "\\src\\main\\java")
.commentDate("yyyy-MM-dd")
.dateType(DateType.TIME_PACK)
)
.packageConfig((builder) ->
builder.parent("com.yu.mybatis_plus")
.entity("pojo")
.service("service")
.serviceImpl("service.impl")
.mapper("mapper")
.xml("mapper.xml")
.pathInfo(Collections.singletonMap(OutputFile.xml, System.getProperty("user.dir") + "\\src\\main\\resources\\mapper"))
)
.injectionConfig((builder) ->
builder.beforeOutputFile(
(a, b) -> log.warn("tableInfo: " + a.getEntityName())
)
)
.strategyConfig((scanner, builder) ->
builder.addInclude(getTables(scanner.apply("请输入表名,多个英文逗号分隔?所有输入 all")))
.addTablePrefix("tb_", "t_", "lay_", "meeting_", "sys_")
.entityBuilder()
.enableChainModel()
.enableLombok()
.enableTableFieldAnnotation()
.controllerBuilder()
.enableRestStyle()
.enableHyphenStyle()
.build()
)
.templateEngine(new FreemarkerTemplateEngine())
.execute();
}
protected static List<String> getTables(String tables) {
return "all".equals(tables) ? Collections.emptyList() : Arrays.asList(tables.split(","));
}
}
创建好生成器文件后需要修改自己的数据库配置信息和生成路径
注意点:
1.创建完成后,因为生成器不会帮我们生成,所以需要自己手动加入在Mapper类中加入@Repository注解,交给spring进行管理
2.在启动类中要使用注解@MapperScan("包名")进行扫码Mapper
例如@MapperScan("com.yu.mybatis_plus")
三.自动生成策略
在 MyBatis-Plus 中,主键生成策略是指在插入一条记录时,如何生成并设置主键的方式。MyBatis-Plus 提供了多种主键生成策略,可以根据业务需求选择合适的方式
1.雪花算法
雪花算法是一种分布式的唯一ID生成算法,能够在分布式系统中生成全局唯一的ID。MyBatis-Plus 提供了
IdType.ASSIGN_ID
来使用雪花算法生成主键
@TableId注解type属性IdType
主键生成策略介绍:
值 | 描述 |
---|---|
AUTO | 数据库 ID 自增 |
NONE | 无状态,该类型为未设置主键类型(注解里等于跟随全局,全局里约等于 INPUT) |
INPUT | insert 前自行 set 主键值 |
ASSIGN_ID | 分配 ID(主键类型为 Number(Long 和 Integer)或 String)(since 3.3.0),使用接口IdentifierGenerator 的方法nextId (默认实现类为DefaultIdentifierGenerator 雪花算法) |
ASSIGN_UUID | 分配 UUID,主键类型为 String(since 3.3.0),使用接口IdentifierGenerator 的方法nextUUID (默认 default 方法) |
导入依赖
<dependency>
<groupId>com.github.yitter</groupId>
<artifactId>yitter-idgenerator</artifactId>
<version>1.0.6</version>
</dependency>
指定Auto,增加一个自增
/**
* 书本编号
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
在Controller层将雪花ID设置成id
@RequestMapping("/save")
public Object save(Book book){
book.setId(YitIdHelper.nextId());
return bookService.save(book);
}
2.测试工具进行接口测试(Postman)
当我们对接口进行发送请求测试不带ID
生成时自动生成雪花ID插入
四.自动填充策略
@TableField字段注解(非主键),其中fill字段自动填充策略,具体策略如下:
值 | 描述 |
---|---|
DEFAULT | 默认不处理 |
INSERT | 插入时填充字段 |
UPDATE | 更新时填充字段 |
INSERT_UPDATE | 插入和更新时填充字段 |
注解则是指定该属性在对应情况下必有值,如果无值则入库会是null
。
1.自定义实现类 MyMetaObjectHandler
@Slf4j
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
@Override
public void insertFill(MetaObject metaObject) {
log.info("开始新增操作自动填充 ....");
this.strictInsertFill(metaObject, "createdate", LocalDateTime.class, LocalDateTime.now());
}
@Override
public void updateFill(MetaObject metaObject) {
log.info("开始更新操作自动填充 ....");
this.strictUpdateFill(metaObject, "createdate", LocalDateTime.class, LocalDateTime.now());
}
}
情况一:fill = FieldFill.DEFAULT,无论是新增和更新都不进行自动填充;
情况二:fill = FieldFill.INSERT,执行新增操作自动填充数据;
情况三:fill = FieldFill.UPDATE,执行更新操作,若字段不为空则自动填充数据;再次执行更新操作不会刷新数据。