前言
在介绍MyBatis-Plus之前还是要先简单介绍一下MyBatis。
MyBatis是一个Java持久化框架,他可以简化实现MySQL操作
- SQL语句的编写:MyBatis将SQL语句和Java代码解耦,使用XML文件或注解编写SQL语句,降低了代码的耦合度。
- 对象关系映射(ORM):MyBatis通过配置文件或者注解将Java对象与数据库表进行映射,从而实现Java对象与数据库表的关联
- 数据库连接管理:Mybatis使用数据源来管理数据库连接,提高了数据库的访问效率。同时可以自定义连接池大小、超时时间等参数,以适应不同场景下的需求。
- 分页查询:Mybatis提供了分页查询的支持,可以通过配置文件或注解来实现分页查询。
总的来说,Mybatis在MySQL操作上的简化体现在SQL语句编写、ORM、连接管理、分页查询、动态SQL支持等方面,提高了程序开发效率,降低了开发难度。
那么我们来介绍下连接池
连接池:
MyBatis连接池是一个用于管理数据库连接的对象池。当应用程序需要连接到数据库时,它可以从连接池中获取可用的连接,而不必每次都创建新的连接。这可以提高应用程序的性能和可伸缩性。
连接池通常在应用程序启动时初始化,并在应用程序关闭时销毁。连接池的大小取决于应用程序的需求和底层系统的资源限制。如果连接池已满,应用程序仍需要连接,则会阻塞直到有可用连接或等待超时。
MyBatis连接池定义了一组规则来管理连接,例如最大空闲时间、最大活动连接数以及连接回收策略等。这些规则可以通过配置文件进行设置。
MyBatis连接池具有各种可配置的属性,以下是一些常用的配置选项:
driver
:指定数据库驱动类名。
url
:指定数据库连接字符串。
username
:指定数据库用户名。
password
:指定数据库密码。
initialSize
:连接池中初始化连接数。
maxActive
:连接池中最大活动连接数。
maxIdle
:连接池中最大空闲连接数。
minIdle
:连接池中最小空闲连接数。
maxWait
:获取连接的最大等待时间(毫秒)。
timeBetweenEvictionRunsMillis
:连接回收器线程运行间隔时间。
minEvictableIdleTimeMillis
:连接在池中保持空闲而不被使用的最短时间。
testWhileIdle
:是否开启空闲连接检测。
testOnBorrow
:是否开启获取连接时的检测。
testOnReturn
:是否开启归还连接时的检测。
validationQuery
:用来检验连接是否有效的 SQL 语句。
removeAbandoned
:是否移除废弃的连接。
removeAbandonedTimeout
:废弃连接超时时间。
这些配置选项可以通过在 MyBatis 配置文件中添加
<dataSource>
元素来设置。例如:<dataSource type="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/mybatis"/> <property name="user" value="root"/> <property name="password" value="root"/> <property name="initialPoolSize" value="5"/> <property name="maxPoolSize" value="10"/> <property name="minPoolSize" value="2"/> <property name="maxIdleTime" value="3600"/> </dataSource>
MyBatis-Plus简介
ok,我们言归正传开始介绍MyBatis-Plus相关内容。
MyBatis-Plus是一个MyBatis的增强工具,在MyBatis的基础上只做增强不做改变,为进化开发,提高效率而生。没错MyBatis在传统JDBC的基础上做了简化,而MyBatis-Plus又在MyBatis的基础上做了简化。
具体特性如下:
- 无侵入:只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑
- 损耗小:启动即会自动注入基本 CURD,性能基本无损耗,直接面向对象操作
- 强大的 CRUD 操作:内置通用 Mapper、通用 Service,仅仅通过少量配置即可实现单表大部分 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 操作智能分析阻断,也可自定义拦截规则,预防误操作
框架结构

如何使用
具体使用使用方法请看 https://baomidou.com/pages/226c21/#初始化工程
注意点:
在 Spring Boot 启动类中添加
@MapperScan
注解,扫描 Mapper 文件夹:注解
属性 | 类型 | 必须指定 | 默认值 | 描述 |
value | String | 否 | "" | 表名 |
schema | String | 否 | "" | schema |
keepGlobalPrefix | boolean | 否 | false | 是否保持使用全局的 tablePrefix 的值(当全局 tablePrefix 生效时) |
resultMap | String | 否 | "" | xml 中 resultMap 的 id(用于满足特定类型的实体类对象绑定) |
autoResultMap | boolean | 否 | false | 是否自动构建 resultMap 并使用(如果设置 resultMap 则不会进行 resultMap 的自动构建与注入) |
excludeProperty | String[] | 否 | {} | 需要排除的属性名 @since 3.3.1 |
属性 | 类型 | 必须指定 | 默认值 | 描述 |
value | String | 否 | "" | 主键字段名 |
type | Enum | 否 | IdType.NONE | 指定主键类型 |
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 方法) |
分布式全局唯一 ID 长整型类型(please use ASSIGN_ID ) | |
32 位 UUID 字符串(please use ASSIGN_UUID ) | |
分布式全局唯一 ID 字符串类型(please use ASSIGN_ID ) |
备注:这个值也可以在配置文件中设置默认值
属性 | 类型 | 必须指定 | 默认值 | 描述 |
value | String | 否 | "" | 数据库字段名 |
exist | boolean | 否 | true | 是否为数据库表字段 |
condition | String | 否 | "" | |
update | String | 否 | "" | 字段 update set 部分注入,例如:当在version字段上注解update="%s+1" 表示更新时会 set version=version+1 (该属性优先级高于 el 属性) |
insertStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_NULL insert into table_a(<if test="columnProperty != null">column</if>) values (<if test="columnProperty != null">#{columnProperty}</if>) |
updateStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:IGNORED update table_a set column=#{columnProperty} |
whereStrategy | Enum | 否 | FieldStrategy.DEFAULT | 举例:NOT_EMPTY where <if test="columnProperty != null and columnProperty!=''">column=#{columnProperty}</if> |
fill | Enum | 否 | FieldFill.DEFAULT | 字段自动填充策略 |
select | boolean | 否 | true | 是否进行 select 查询 |
keepGlobalFormat | boolean | 否 | false | 是否保持使用全局的 format 进行处理 |
jdbcType | JdbcType | 否 | JdbcType.UNDEFINED | JDBC 类型 (该默认值不代表会按照该值生效) |
typeHandler | Class<? extends TypeHandler> | 否 | UnknownTypeHandler.class | 类型处理器 (该默认值不代表会按照该值生效) |
numericScale | String | 否 | "" | 指定小数点后保留的位数 |
- @Version
描述:乐观锁注解、标记
@Version
在字段上- @EnumValue
描述:普通枚举类注解(注解在枚举字段上)
描述:表字段逻辑处理注解(逻辑删除)
属性 | 类型 | 必须指定 | 默认值 | 描述 |
value | String | 否 | "" | 逻辑未删除值 |
delval | String | 否 | "" | 逻辑删除值 |
- @KeySequence
- 描述:序列主键策略
oracle
- 属性:value、dbType
属性 | 类型 | 必须指定 | 默认值 | 描述 |
value | String | 否 | "" | 序列名 |
dbType | Enum | 否 | DbType.OTHER | 数据库类型,未配置默认使用注入 IKeyGenerator 实现,多个实现必须指定 |
- 描述:内置 SQL 默认指定排序,优先级低于 wrapper 条件查询
属性 | 类型 | 必须指定 | 默认值 | 描述 |
isDesc | boolean | 否 | true | 是否倒序查询 |
sort | short | 否 | Short.MAX_VALUE | 数字越小越靠前 |
MyBatis-Plus分页原理
MyBatis-Plus 分页采用了分页插件来实现。
分页插件的原理是在查询语句执行前,先通过拦截器将原始 SQL 语句改造成对应的分页 SQL 语句,并在其中添加分页限制条件,然后再执行查询操作。分页插件会通过 Page 对象来控制分页信息,Page 对象包含了分页参数(当前页、每页显示数量)以及分页结果(总记录数、总页数、分页数据列表)等信息。
MyBatis-Plus 的分页插件提供了两种方式来实现分页:
- 基于 RowBounds 的分页
基于 RowBounds 实现的分页,即是查询时指定一个 RowBounds 对象,该对象包含了分页的信息,MyBatis-Plus 会拦截这个查询并进行改造,然后再执行查询操作。这种方式的优点是可以使用多种数据库的分页机制,但缺点就是需要手动传入 RowBounds 对象。
- 基于 PageHelper 的分页
基于 PageHelper 实现的分页,使用起来非常方便,只需要在查询方法中传入一个 Page 对象即可。MyBatis-Plus 会自动拦截该查询,并进行分页改造。这种方式的优点是使用起来非常简单,但缺点就是只能使用一种数据库的分页机制。
MyBatis-Plus插件
MybatisPlusInterceptor
该插件是核心插件,目前代了 Executor#query
和 Executor#update
和 StatementHandler#prepare
方法属性
private List<InnerInterceptor> interceptors = new ArrayList<>();
InnerInterceptor
我们提供的插件都将基于此接口来实现功能
目前已有的功能:
- 自动分页: PaginationInnerInterceptor
- 多租户: TenantLineInnerInterceptor
- 动态表名: DynamicTableNameInnerInterceptor
- 乐观锁: OptimisticLockerInnerInterceptor
- sql 性能规范: IllegalSQLInnerInterceptor
- 防止全表更新与删除: BlockAttackInnerInterceptor
使用方式:
spring-boot
@Configuration @MapperScan("scan.your.mapper.package") public class MybatisPlusConfig { /** * 新的分页插件,一缓和二缓遵循mybatis的规则,需要设置 MybatisConfiguration#useDeprecatedExecutor = false 避免缓存出现问题(该属性会在旧插件移除后一同移除) */ @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.H2)); return interceptor; } @Bean public ConfigurationCustomizer configurationCustomizer() { return configuration -> configuration.setUseDeprecatedExecutor(false); } }
乐观锁
当要更新一条记录的时候,希望这条记录没有被别人更新乐观锁实现方式:
取出记录时,获取当前 version更新时,带上这个 version执行更新时, set version = newVersion where version = oldVersion如果 version 不对,就更新失败
@Version private Integer version;
说明:
- 支持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下
newVersion = oldVersion + 1
newVersion
会回写到entity
中
- 仅支持
updateById(id)
与update(entity, wrapper)
方法
- 在
update(entity, wrapper)
方法下,wrapper
不能复用!!!