img
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,它在 MyBatis 的基础上提供了丰富的功能,简化了开发过程,提高了开发效率。
MyBatis-Plus 只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑。其特性包括效率至上,只需简单配置,即可快速进行单表 CRUD 操作,从而节省大量时间;还拥有丰富的功能,如代码生成、自动分页、逻辑删除、自动填充、拦截器等。
MyBatis-Plus 连续 5 年获得开源中国年度最佳开源项目殊荣,在 Github 上累计获得 16K Star。它支持多种数据库,包括 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等。
使用 MyBatis-Plus 时,可以通过 Maven 或 Gradle 添加依赖。以 Maven 为例,添加依赖的方式如下:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus</artifactId>
<version>3.5.9</version>
</dependency>
MyBatis-Plus 还拥有一些强大的插件和工具,如苞米豆生态圈中的 MybatisX,是一款全免费且强大的 IDEA 插件,支持跳转、自动补全生成 SQL、代码生成等功能;Mybatis-Mate 为 MyBatis-Plus 企业级模块,支持分库分表、数据审计、字段加密、数据绑定、数据权限、表结构自动生成 SQL 维护等高级特性;还有 AiZuDa 爱组搭 - 低代码开发平台组件库、FlowLong 真正的国产工作流引擎、SnailJob 分布式任务重试和调度平台、Dynamic-Datasource 基于 SpringBoot 的多数据源组件、Lock4j 基于 SpringBoot 同时支持 RedisTemplate、Redission、Zookeeper 的分布式锁组件、Shuan 基于 Pac4J-JWT 的 WEB 安全组件、Kisso 基于 Cookie 的单点登录组件、Kaptcha 基于 SpringBoot 和 Google Kaptcha 的简单验证码组件等。
MyBatis-Plus 已连续 5 年(2017、2018、2019、2020、2021)获得 “OSC 年度最受欢迎中国开源软件” 殊荣,其开发团队会秉承 “为简化开发而生” 这一理念砥砺前行。代码托管在 Gitee 和 Github 上,欢迎各路好汉一起来参与完善 MyBatis-Plus,大家可以贡献代码、提交 Issue 或者 Pull Requests,也可以参与翻译和修订教程、案例、使用者名单等。
MyBatis-Plus 的优点
img
1. 依赖少,仅依赖 MyBatis 和 MyBatis-Spring。
MyBatis-Plus 仅依赖 MyBatis 和 MyBatis-Spring,这使得它能够在不引入过多额外依赖的情况下,为开发者提供强大的功能。这种简洁的依赖关系使得项目的构建和管理更加容易,同时也减少了潜在的冲突和兼容性问题。
2. 启动即自动注入基本 CURD,性能损耗小。
在项目启动时,MyBatis-Plus 能够自动注入基本的 CURD(Create、Read、Update、Delete)操作,这大大提高了开发效率。而且,由于其性能损耗小,开发者可以在不担心性能问题的前提下,快速进行数据库操作。
3. 内置 Sql 注入剥离器,预防 Sql 注入攻击。
MyBatis-Plus 内置了 Sql 注入剥离器,能够有效地预防 Sql 注入攻击。这对于保障数据库的安全至关重要,使得开发者可以更加放心地进行数据库操作,而不必担心恶意用户的攻击。
4. 通用 CRUD 操作,内置通用 Mapper、通用 Service。
MyBatis-Plus 提供了通用的 CRUD 操作,内置了通用 Mapper 和通用 Service。这使得开发者只需通过少量配置即可实现单表大部分的 CRUD 操作,大大简化了开发过程。同时,强大的条件构造器也满足了各类使用需求,使得查询操作更加灵活和高效。
5. 多种主键策略,支持分布式唯一 ID 生成器。
MyBatis-Plus 支持多种主键策略,包括 AUTO(使用数据库自增 ID)、INPUT(insert 前自行为主键赋值)、NONE(无状态,约等于 INPUT)、ASSIGN_ID(分配 ID,使用雪花算法)、ASSIGN_UUID(分配 UUID)。此外,它还支持分布式唯一 ID 生成器,完美解决了主键问题。
6. Mapper 对应的 XML 支持热加载。
MyBatis-Plus 的 Mapper 对应的 XML 支持热加载,对于简单的 CRUD 操作,甚至可以无 XML 启动。这使得开发过程更加高效,开发者可以在不重启项目的情况下,快速修改和测试 SQL 语句。
7. 支持 ActiveRecord 形式调用。
MyBatis-Plus 支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可实现基本 CRUD 操作。这种方式使得代码更加简洁和易于维护,提高了开发效率。
8. 支持代码生成,可快速生成多层代码。
MyBatis-Plus 支持代码生成,采用代码或者 Maven 插件可快速生成 Mapper、Model、Service、Controller 层代码。它还支持模板引擎,有超多自定义配置等,大大提高了开发效率,减少了重复劳动。
9. 支持自定义全局通用操作。
MyBatis-Plus 支持全局通用方法注入,即 Write once, use anywhere。这使得开发者可以在 Mapper 和 Service 层添加自定义的方法,实现一次编写,多处使用,提高了代码的可复用性。
10. 支持关键词自动转义。
MyBatis-Plus 支持数据库关键词(order、key…)自动转义,还可自定义关键词。这有效地避免了因关键词冲突而导致的 SQL 语句错误,提高了代码的稳定性和可靠性。
11. 内置分页插件。
MyBatis-Plus 内置分页插件,基于 Mybatis 的物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询。目前 MP 已经存在的内部插件包括分页插件【PaginationInnerInterceptor】,它支持的数据库包括 mysql、oracle、db2、h2、hsql、sqlite、postgresql、sqlserver 等几乎市面上所有常用的数据库。插件使用也很简单,只需在配置类中添加如下代码即可:
@Configuration
public class MybatisPlusConfig {
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}
12. 内置性能分析插件。
MyBatis-Plus 内置性能分析插件,可输出 Sql 语句以及其执行时间。建议开发测试时启用该功能,能有效解决慢查询问题。
13. 内置全局拦截插件。
MyBatis-Plus 内置全局拦截插件,提供全表 delete、update 操作智能分析阻断,预防误操作。
MyBatis-Plus 的性能分析
img
1. 原理:通过 AOP 实现,在 MyBatis 的执行过程中插入拦截器,采集和统计 SQL 执行前后的性能数据。
MyBatis-Plus 的性能分析功能是通过面向切面编程(AOP)实现的。它在 MyBatis 的执行过程中插入拦截器,在 SQL 执行之前和之后进行性能数据的采集和统计。具体来说,MyBatis-Plus 通过解析传入的条件参数,自动生成相应的 SQL 片段,进而实现复杂的查询逻辑。在这个过程中,性能分析拦截器会记录 SQL 语句的执行时间等性能数据。
2. 使用方法:引入依赖,在项目中配置性能分析插件,可设置 SQL 执行时间阈值进行拦截。
首先需要在项目中引入 MyBatis-Plus 的依赖,以 Maven 项目为例,可以添加以下依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.9</version>
</dependency>
然后在项目中配置性能分析插件。可以通过在配置类中添加以下代码来配置性能分析插件:
@Configuration
public class MyBatisPlusConfig {
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(1000); // 设置 SQL 执行时间阈值为 1000 毫秒
performanceInterceptor.setFormat(true); // 开启 SQL 格式化
return performanceInterceptor;
}
}
配置好性能分析插件后,可以在开发和测试环境中启用该功能,帮助开发者快速揪出慢查询问题,优化 SQL 语句,提高数据库操作的性能。
MyBatis-Plus 的使用教程
img
-
环境搭建:
-
-
添加依赖:MyBatis-Plus 可以通过 Maven 或 Gradle 添加依赖。以 Maven 为例,添加依赖的方式如下:
-
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.5.9</version>
</dependency>
-
配置数据库连接:在项目的配置文件中配置数据库连接信息,例如在 Spring Boot 项目中,可以在 application.properties 或 application.yml 文件中进行配置。以 application.yml 为例,配置如下:
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/your_database?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8
username: root
password: root
-
创建实体类和 Mapper 接口:实体类通常对应数据库中的表结构,使用注解进行映射。例如:
@Data
@TableName("your_table_name")
public class YourEntity {
@TableId(type = IdType.AUTO)
private Long id;
// 其他字段...
}
Mapper 接口继承 BaseMapper,指定实体类类型:
public interface YourMapper extends BaseMapper<YourEntity> {}
-
配置 Mapper 扫描:在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 接口所在的包。例如:
@SpringBootApplication
@MapperScan("your.package.path")
public class YourApplication {
public static void main(String[] args) {
SpringApplication.run(YourApplication.class, args);
}
}
-
基本 CRUD 操作:
-
-
插入:使用 Mapper 接口的 insert 方法进行插入操作。例如:
-
YourEntity entity = new YourEntity();
// 设置实体属性
yourMapper.insert(entity);
-
查询:可以使用 selectById、selectList 等方法进行查询。例如:
YourEntity entityById = yourMapper.selectById(id);
List<YourEntity> entityList = yourMapper.selectList(null);
-
更新:使用 updateById 或 update 方法进行更新操作。例如:
YourEntity updatedEntity = new YourEntity();
// 设置更新后的属性和主键
yourMapper.updateById(updatedEntity);
-
删除:可以使用 deleteById、deleteBatchIds 等方法进行删除操作。例如:
yourMapper.deleteById(id);
List<Long> ids = Arrays.asList(1L, 2L, 3L);
yourMapper.deleteBatchIds(ids);
-
高级功能:
-
-
分页查询:
-
-
-
-
添加分页插件依赖:确保项目中添加了 MyBatis-Plus 的分页插件依赖。
-
-
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>合适的版本号</version>
</dependency>
-
配置分页插件:在配置类中添加分页插件的配置。
@Configuration
public class MybatisPlusConfig {
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
-
创建 Page 对象:在服务层或控制器层,创建一个 Page 对象,指定页码和每页条数。
Page<YourEntity> page = new Page<>(1, 10);
-
调用分页查询方法:可以使用 LambdaQueryWrapper 设置查询条件,然后调用 Mapper 的 selectPage 方法进行分页查询。
LambdaQueryWrapper<YourEntity> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(YourEntity::getSomeField, someValue);
Page<YourEntity> yourEntityPage = yourMapper.selectPage(page, queryWrapper);
-
条件构造器:
-
-
MyBatis-Plus 的条件构造器主要有 QueryWrapper 和 LambdaQueryWrapper,用于构建复杂的查询条件。
-
-
-
例如,使用 LambdaQueryWrapper 进行查询:
-
LambdaQueryWrapper<YourEntity> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(YourEntity::getName, "Jack");
lambdaQueryWrapper.gt(YourEntity::getAge, 18);
lambdaQueryWrapper.likeRight(YourEntity::getName, "J");
List<YourEntity> entities = yourMapper.selectList(lambdaQueryWrapper);
-
代码生成器:
-
-
AutoGenerator 是 MyBatis-Plus 的代码生成器,可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码。
-
-
-
使用步骤如下:
-
-
-
配置代码生成器:
-
AutoGenerator mpg = new AutoGenerator();
DataSourceConfig dataSourceConfig = new DataSourceConfig();
dataSourceConfig.setUrl("your_database_url");
dataSourceConfig.setDriverName("your_driver_name");
dataSourceConfig.setUsername("your_username");
dataSourceConfig.setPassword("your_password");
mpg.setDataSource(dataSourceConfig);
-
设置全局配置:
GlobalConfig globalConfig = new GlobalConfig();
globalConfig.setOutputDir("your_output_directory");
globalConfig.setAuthor("your_name");
mpg.setGlobalConfig(globalConfig);
-
设置策略配置:
StrategyConfig strategyConfig = new StrategyConfig();
strategyConfig.setInclude("your_table_names");
mpg.setStrategy(strategyConfig);
-
执行代码生成:
mpg.execute();
MyBatis-Plus 的实际应用案例
img
1. 逻辑删除:
MyBatis-Plus 提供了便捷的逻辑删除功能。通过给表增加 deleted 字段,然后配置 MyBatis-Plus 的全局配置,如在 mybatis-plus 的全局配置中进行如下设置:
global-config:
db-config:
# 全局逻辑删除的实体字段名(since 3.3.0,配置后可以忽略不配置步骤2)
logic-delete-field: flag
# 逻辑已删除值(默认为1)
logic-delete-value: 1
# 逻辑未删除值(默认为0)
logic-not-delete-value: 0
在实体类字段上添加 @TableLogic 注解,例如:
@TableLogic()
@TableField(select = false)
private Integer deleted;
这样就可以实现逻辑删除和查询未删除数据的功能。在进行删除操作时,实际上是更新 deleted 字段的值,而不是真正从数据库中删除数据。例如:
@Test
public void apiTest(){
// UPDATE test.user SET deleted=1 WHERE user_id=? AND deleted=0
logger.info("开始逻辑删除");
int count = userDAO.deleteById(356);
// SELECT * FROM test.user WHERE user_id=? AND deleted=0
logger.info("开始查询");
User user;
}
2. 通用枚举:
在开发中,当实体对象涉及到状态等固定值的变化时,可以使用 MyBatis-Plus 的通用枚举功能。声明通用枚举属性有多种方式,例如:
-
方式一:使用 @EnumValue 注解枚举属性。
@Getter
@AllArgsConstructor
public enum StatusEnum {
SHOW(1,"显示"),
HIDE(2,"隐藏");
@EnumValue
@JsonValue
private Integer code;
private String descp;
}
-
方式二:枚举属性实现 IEnum 接口。
public interface IEnum<T extends Serializable> {
T getValue();
}
@Getter
@AllArgsConstructor
public enum StatusEnum implements IEnum<Integer> {
SHOW(1,"显示"),
HIDE(2,"隐藏");
private Integer code;
private String descp;
@Override
public Integer getValue() {
return this.code;
}
}
实体属性使用枚举类型,在配置序列化方式时,可以在枚举类上添加 @JsonValue 注解进行序列化操作,例如:
@Getter
public enum SexEnum {
MALE(1,"男"),
FEMALE(0,"女");
@EnumValue
private int status;
@JsonValue
private String label;
private SexEnum(int status,String label){
this.status = status;
this.label = label;
}
}
同时,需要配置扫描通用枚举,在配置文件中添加以下配置:
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
type-aliases-package: com.study.demo.pojo
# 配置扫描通用枚举
type-enums-package: com.study.demo.enums
3. 自动填充功能:
在项目中,经常会遇到一些数据需要每次以相同方式填充,比如记录的创建时间和更新时间。可以通过以下步骤实现自动填充功能。
首先,修改表结构增加创建时间和更新时间字段,例如在 User 表中添加 datetime 类型的新字段 create_time、update_time。
然后,在实体类字段上添加 @TableField 和 FieldFill 注解,例如:
@Data
public class User {
//...
@TableField(fill = FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
最后,自定义实现类 MyMetaObjectHandler 实现自动填充功能,注意要添加 @Component 注解。
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
// 使用 mp 实现添加操作,这个方法执行
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
this.setFieldValByName("version",1,metaObject);
}
// 使用 mp 实现修改操作,这个方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
总结
MyBatis-Plus 作为一个强大的 Java 持久层框架,具有众多优点和丰富的功能,在实际开发中能够大大提高开发效率。虽然项目引入第三方插件包可能存在未来升级的兼容性问题和技术文档更新不及时的情况,但总体来说,MyBatis-Plus 是一个值得推荐的框架。
引入第三方插件包可能带来的兼容性问题需要开发者在使用过程中密切关注框架的更新动态,并及时进行测试和调整。技术文档更新不及时可能会给开发者在遇到问题时的查找解决方案带来一定的困难,这就需要开发者积极参与社区讨论,或者通过查看相关的开源项目案例来获取更多的使用经验。
然而,MyBatis-Plus 的优点远远超过了这些可能存在的问题。其简洁的依赖关系、强大的功能以及丰富的插件生态,使得它在 Java 开发领域中备受青睐。无论是小型项目还是大型企业级应用,MyBatis-Plus 都能提供高效的数据库操作解决方案,为开发者节省大量的时间和精力。