简介:
MyBatis-Plus(简称 MP)是一个 MyBatis 的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。
润物无声,只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑,效率至上
只需简单配置,即可快速进行 CRUD 操作,从而节省大量时间。有丰富功能:热加载、代码生成、分页、性能分析等功能一应俱全。
配置:
在 application.properties 配置文件中添加 MySQL 数据库的相关配置:
spring boot 2.0(内置jdbc5驱动)
#mysql数据库连接 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?characterEncoding=utf-8&useSSL=false spring.datasource.username=root spring.datasource.password=654321 |
spring boot 2.1及以上(内置jdbc8驱动)
注意:driver和url的变化
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8 spring.datasource.username=root spring.datasource.password=654321 |
#mysql数据库连接
spring:
# 数据源配置
datasource:
username: root
password: 654321
url: jdbc:mysql://localhost:3306/yeb?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
hikari:
pool-name: DateHikariCP # 连接池名字
connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
minimum-idle: 5 # 最小连接数
maximum-pool-size: 20 # 最大连接数
auto-commit: true # 事务自动提交
idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
max-lifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms
connection-test-query: SELECT 1 # 连接测试语句
注意:
1、这里的 url 使用了 ?serverTimezone=GMT%2B8 后缀,因为8.0版本的jdbc驱动需要添加这个后缀,否则运行测试用例报告如下错误:
java.sql.SQLException: The server time zone value 'Öйú±ê׼ʱ¼ä' is unrecognized or represents more
2、这里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建议使用这个驱动,否则运行测试用例的时候会有 WARN 信息
1.在启动类
在 Spring Boot 启动类中添加 @MapperScan 注解,扫描 Mapper 文件夹
@SpringBootApplication
|
2.在实体类添加实体
创建包 entity(pojo || po) 编写实体类 Classname.java(此处使用了 Lombok 简化代码)
//例如: @Data |
3.添加mapper
创建包 mapper 编写Mapper 接口: Classname.java
//mapper层 @Repository |
4.测试
添加测试类,进行功能测试:
@SpringBootTest |
注意:IDEA在 userMapper 处报错,是因为找不到注入的对象,因为类是动态创建的,但是程序可以正确的执行。为了避免报错,可以在 dao 层 的接口上添加 @Repository 注解。通过以上几个简单的步骤,就已经实现了 User 表的 CRUD 功能,甚至连 XML 文件都不用编写!
配置文件里配置的查看sql输出日志
#mybatis日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl |
主键策略(注意:数据库插入id值默认为:全局唯一id)?
- MP的主键策略 :ASSIGN_ID,MyBatis-Plus默认的主键策略是:ASSIGN_ID (使用了雪花算法)
@TableId(type = IdType.ASSIGN_ID) private String id; |
雪花算法:分布式ID生成器
雪花算法是分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性。核心思想:长度共64bit(一个long型)整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高。
AUTO 自增策略
需要在创建数据表的时候设置主键自增
实体字段中配置 @TableId(type = IdType.AUTO)
@TableId(type = IdType.AUTO) private Long id; |
要想影响所有实体的配置,可以设置全局主键配置
#全局设置主键生成策略 mybatis-plus.global-config.db-config.id-type=auto |
自动填充和乐观锁?
自动填充
需求描述:
项目中经常会遇到一些数据,每次都使用相同的方式填充,例如记录的创建时间,更新时间等。
我们可以使用MyBatis Plus的自动填充功能,完成这些字段的赋值工作
例如:数据库修改
在User表中添加datetime类型的新的字段 create_time、update_time
实体类修改
实体上增加字段并添加自动填充注解
@TableField(fill = FieldFill.INSERT) |
实现元对象处理器接口
注意:不要忘记添加 @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);
}
//mp执行修改操作,这个方法执行
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
} |
乐观锁?
主要适用场景:当要更新一条记录的时候,希望这条记录没有被别人更新,也就是说实现线程安全的数据更新
乐观锁实现方式:
取出记录时,获取当前version更新时,带上这个version,执行更新时, set version = new Version where version = oldVersion如果version不对,就更新失败
乐观锁实现流程?
1.在数据库新增字段version
2.修改实体类
添加 @Version 注解
@Version private Integer version; |
3.创建配置文件,创建包config,创建文件MybatisPlusConfig.java。此时可以删除主类中的 @MapperScan 扫描注解
@Configuration |
注册乐观锁插件
在 MybatisPlusConfig 中注册 Bean
/** 乐观锁插件*/ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } |
查询?
MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能
添加分页插件
配置类中添加@Bean配置
/** |
逻辑删除?
物理删除和逻辑删除
物理删除:真实删除,将对应数据从数据库中删除,之后查询不到此条被删除数据
逻辑删除:假删除,将对应数据中代表是否被删除字段状态修改为“被删除状态”,之后在数据库中仍旧能看到此条数据记录
逻辑删除的使用场景:可以进行数据恢复,有关联数据,不便删除
逻辑删除实现流程:
1.数据库修改
添加 deleted字段
ALTERTABLE `表名` ADD COLUMN `deleted` boolean DEFAULT false |
2.实体类修改
添加deleted 字段,并加上 @TableLogic 注解
@TableLogic private Integer deleted; |
3.配置(可选)
application.properties 加入以下配置,此为默认值,如果你的默认值和mp默认的一样,该配置可无
mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0 |
4. 测试
测试后发现,数据并没有被删除,deleted字段的值由0变成了1
测试后分析打印的sql语句,是一条update
注意:被删除前,数据的deleted 字段的值必须是 0,才能被选取出来执行逻辑删除的操作
@Test public void testLogicDelete() { int result = userMapper.deleteById(1L) system.out.println(result); } |
5.测试逻辑删除后的查询
MyBatis Plus中查询操作也会自动添加逻辑删除字段的判断
@Test public void testLogicDeleteSelect() { List<User> users = userMapper.selectList(null); users.forEach(System.out::println); } |
条件构造器和常用接口?
- wapper介绍
Wrapper : 条件构造抽象类,最顶端父类
AbstractWrapper : 用于查询条件封装,生成 sql 的 where 条件
QueryWrapper : 查询条件封装
UpdateWrapper : Update 条件封装
AbstractLambdaWrapper : 使用Lambda 语法
LambdaQueryWrapper :用于Lambda语法使用的查询Wrapper
LambdaUpdateWrapper : Lambda 更新封装Wrapper
测试用:ge、gt、le、lt、isNull、isNotNull
@SpringBootTest public class QueryWrapperTests { @Autowired private UserMapper userMapper; @Test public void testQuery() { QueryWrapper<User>queryWrapper = newQueryWrapper<>(); queryWrapper .isNull("name") .ge("age", 12) .isNotNull("email"); int result = userMapper.delete(queryWrapper); System.out.println("delete return count = " + result); } } |
eq、ne
注意:seletOne()返回的是一条实体记录,当出现多条时会报错
@Test public void testSelectOne() { QueryWrapper<User> queryWrapper = new QueryWrapper<>(); queryWrapper.eq("name", "Tom"); Useruser = userMapper.selectOne(queryWrapper);//只能返回一条记录,多余一条则抛出异常 System.out.println(user); } |
between、notBetween包含大小边界
@Test public void testSelectCount() { QueryWrapper<User>queryWrapper = newQueryWrapper<>(); queryWrapper.between("age", 20, 30); Integer count = userMapper.selectCount(queryWrapper); //返回数据数量 System.out.println(count); } |
like、notLike、likeLeft、likeRight
selectMaps()返回Map集合列表,通常配合select()使用
@Test public void testSelectMaps() { QueryWrapper<User>queryWrapper = newQueryWrapper<>(); queryWrapper.select("name", "age") .like("name", "e") .likeRight("email", "5"); List<Map<String, Object>>maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表 maps.forEach(System.out::println); } |
orderBy、orderByDesc、orderByAsc
@Test public void testSelectListOrderBy() { QueryWrapper<User>queryWrapper = newQueryWrapper<>(); queryWrapper.orderByDesc("age", "id"); List<User>users = userMapper.selectList(queryWrapper); users.forEach(System.out::println); } |
查询方式
查询方式 | 说明 |
setSqlSelect | 设置 SELECT 查询字段 |
where | WHERE 语句,拼接 + WHERE 条件 |
and | AND 语句,拼接 + AND 字段=值 |
andNew | AND 语句,拼接 + AND (字段=值) |
or | OR 语句,拼接 + OR 字段=值 |
orNew | OR 语句,拼接 + OR (字段=值) |
eq | 等于= |
allEq | 基于 map 内容等于= |
ne | 不等于<> |
gt | 大于> |
ge | 大于等于>= |
lt | 小于< |
le | 小于等于<= |
like | 模糊查询 LIKE |
notLike | 模糊查询 NOT LIKE |
in | IN 查询 |
notIn | NOT IN 查询 |
isNull | NULL 值查询 |
isNotNull | IS NOT NULL |
groupBy | 分组 GROUP BY |
having | HAVING 关键词 |
orderBy | 排序 ORDER BY |
orderAsc | ASC 排序 ORDER BY |
orderDesc | DESC 排序 ORDER BY |
exists | EXISTS 条件语句 |
notExists | NOT EXISTS 条件语句 |
between | BETWEEN 条件语句 |
notBetween | NOT BETWEEN 条件语句 |
addFilter | 自由拼接 SQL |
last | 拼接在最后,例如:last(“LIMIT 1”) |
MP的AR模式
什么是AR模式:简单来说就是通过实体类对象,直接进行表的增删改查操作。
AR:Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。实体类只需要继承Model类即可进行强大的CRUD操作。
实现AR模式在MP中有两个基本要求:
- 实体类继承Model类
- 必须存在原始的Mapper接口并继承BaseMapper
什么是MP
MP:MyBatis-Plus (opens new window)(简称 MP)是一个 MyBatis (opens new window)的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生
什么是MP中的AR
AR:Active Record(活动记录),是一种领域模型模式,特点是一个模型类对应关系型数据库中的一个表,而模型类的一个实例对应表中的一行记录。实体类只需要继承Model类即可进行强大的CRUD操作。
MP和AR的关系:
MP是Mybatis-Plus的简称,是一个完整框架体系;AR是指一个模型类对应一个关系型数据库中的一张表;AR只是MP的一个功能而已。