简介
特性:
无侵入: 只做增强不做改变,引入它不会对现有工程产生影响。
损耗小: 启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作, BaseMapper。
强大的 CRUD 操作: 内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分CRUD 操作,更有强大的条件构造器,满足各类使用需求,以后简单的CRUD操作,它不用自己编写了!
支持 Lambda 形式调用: 通过 Lambda 表达式,方便的编写各类查询条件,无需再担心字段写错。
支持主键自动生成: 支持多达 4 种主键策略(内含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解决主键问题。
支持 ActiveRecord 模式: 支持 ActiveRecord 形式调用,实体类只需继承 Model 类即可进行强大的 CRUD 操作。
支持自定义全局通用操作: 支持全局通用方法注入( Write once, use anywhere )。
内置代码生成器: 采用代码或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、Controller 层代码,支持模板引擎,更有超多自定义配置等您来使用(自动生成代码)。
内置分页插件: 基于 MyBatis 物理分页,开发者无需关心具体操作,配置好插件之后,写分页等同于普通 List 查询。
分页插件支持多种数据库: 支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多种数据库。
内置性能分析插件: 可输出 Sql 语句以及其执行时间,建议开发测试时启用该功能,能快速揪出慢查询。
内置全局拦截插件: 提供全表 delete 、 update 操作智能分析阻断,也可自定义拦截规则,预防误操作。
2.快速入门
使用第三方组件套路:
1、导入对应的依赖
2、研究依赖如何配置
3、代码如何编写
4、提高扩展技术能力!
2.1步骤:
1、创建数据库 mybatis_plus
2、创建user表
1 | DROP TABLE IF EXISTS user; |
3、编写项目,初始化项目!使用SpringBoot初始化!
4、导入依赖
1 | <!-- 数据库驱动 --> |
说明:使用 mybatis-plus 可以节省大量的代码,尽量不要同时导入 mybatis 和 mybatis-plus!否则会存在问题!
5、连接数据库!这一步和 mybatis 相同!
1 | # 设置开发环境 |
6、传统方式pojo-dao(连接mybatis,配置mapper.xml文件)-> service -> controller
6、使用了mybatis-plus 之后
pojo
1
2
3
4
5
6
7
8
9
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}mapper接口
1 | import com.baomidou.mybatisplus.core.mapper.BaseMapper; |
注意点,我们需要在主启动类上去扫描我们的mapper包下的所有接口
@MapperScan("com.liu.mapper")
测试类中测试
1 |
|
- 结果:查询结果和预期一样。
思考问题?
1、SQL谁帮我们写的 ? MyBatis-Plus 都写好了。
2、方法哪里来的? MyBatis-Plus 都写好了。
2.2 配置日志
我们所有的sql现在是不可见的,我们希望知道它是怎么执行的,所以我们必须要看日志!
配置完毕日志之后,后面的学习就需要注意这个自动生成的SQL。
1 | # 配置日志 |
3.CRUD扩展
3.1 插入操作
Insert 插入:
1 | // 测试插入 |
3.2 主键生成策略
默认是ID_WORKER: 全局唯一id。
分布式系统唯一id生成: https://www.cnblogs.com/haoxinyue/p/5208136.html
雪花算法:
snowflake是Twitter开源的分布式ID生成算法,结果是一个long型的ID。其核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0。可以保证几乎全球唯一!
举例:使用主键自增策略
1、数据库对应字段一定要是自增!
2、实体类字段上 @TableId(type = IdType.AUTO)
1 |
|
其余的源码解释:
1 | public enum IdType { |
3.3 更新操作
1 | // 测试更新 |
3.4 自动填充
创建时间、修改时间。这些字段的操作一般都是自动化完成的,我们不希望手动更新!
阿里巴巴开发手册:几乎所有的数据库表都要有这两个字段:gmt_create
、gmt_modified
。而且需要自动化!
方式一: 数据库级别(工作中不允许你修改数据库,也不建议使用这种方式)
1、在表中新增字段 create_time, update_time。并设置其更新操作为自动更新,默认值为CURRENT_TIMESTAMP。
2、把实体类同步!
1 |
|
3、再次测试插入方法,查看结果:数据库自动为其更新为当前时间。
方式二: 代码级别(建议)
1、删除create_time, update_time字段的默认值、更新操作:删除方式一设置的默认值与操作。
2、实体类字段属性上需要增加注解
1 |
|
3、编写处理器来处理这个注解即可!
1 | import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; |
4、测试插入
5、测试更新、观察时间即可!
3.5 乐观锁
乐观锁:十分乐观,它总是认为不会出现问题,无论干什么都不去上锁!如果出现了问题,再次更新值测试。
悲观锁:十分悲观,它总是认为总是出现问题,无论干什么都会上锁!再去操作!
这里主要讲解 乐观锁机制!
乐观锁实现方式:
- 取出记录时,获取当前 version。
- 更新时,带上这个version。
- 执行更新时,
set version = newVersion where version = oldVersion
。 - 如果version不对,就更新失败。
举例:
1 | -- 乐观锁:1、先查询,获得版本号 此时version = 1 |
测试一下MyBatisPlus的乐观锁插件:
1、给数据库中增加version字段(乐观锁字段):int类型
2、在实体类中加对应的字段,并添加注解:
1 |
|
3、注册组件
1 | // 扫描我们的 mapper 文件夹(放在这里,就别放到主启动类上了) |
4、测试
1 | // 测试乐观锁 成功案例 |
3.6 查询操作
1 | // 测试查询 |
3.7 分页查询
分页查询方案:
1、原始的 limit 进行分页。
2、pageHelper 第三方插件。
3、MyBatis-Plus内置的分页插件。
如何使用:
1、配置拦截器组件
1 | // 扫描 mapper 文件夹(放在这里,就别放到主启动类上了) |
2、直接使用Page对象即可!
1 | // 测试分页查询 |
3、使用IPage
1 |
|
3.8 基本删除操作
1 | // 根据 id 删除记录 |
3.9逻辑删除
物理删除 :从数据库中直接移除。
逻辑删除 :在数据库中没有被移除,而是通过一个变量来让他失效: deleted = 0 ==> deleted = 1
管理员可以查看被删除的记录!防止数据的丢失,类似于回收站!
1、在数据表中增加一个 deleted 字段:int类型,默认值0(1表示被删除)
2、在实体类中加对应的字段,并添加注解:
1 |
|
3、配置:添加逻辑删除组件。
1 | "com.liu.mapper") ( |
4、添加配置类
1 | # 配置逻辑删除 |
5、测试
1 | // 测试删除 |
3.10 性能分析插件
在平时的开发中,会遇到一些慢sql。可以通过druid等解决。
MyBatis Plus提供性能分析插件,如果超过这个时间就停止运行!
作用:性能分析拦截器,用于输出每条 SQL 语句及其执行时间,从而在开发中找到哪些sql会出现问题。
1、导入插件
1 | "com.liu.mapper") ( |
记住,要在SpringBoot中配置环境为dev或者 test 环境!
1 | # 设置开发环境 |
2、测试使用
1 |
|
3.11 条件构造器
一些复杂的sql就可以使用它来替代!
参考资料:
1、测试一:复杂查询
1 |
|
2、测试二:根据指定字段值查询
1 |
|
3、测试三:查询指定区间的数据
1 |
|
4、测试四:模糊查询
1 | // 模糊查询: |
5、测试五:内查询
1 | // 模糊查询 |
6、测试六:查询后排序
1 | //测试六 |
3.12 代码自动生成器
dao、pojo、service、controller都自动生成!
AutoGenerator 是 MyBatis-Plus 的代码生成器,通过 AutoGenerator 可以快速生成 Entity、Mapper、Mapper XML、Service、Controller 等各个模块的代码,极大的提升了开发效率。
测试:
1 | import com.baomidou.mybatisplus.annotation.DbType; |
结果: