MyBatisPlus

MybatisPlus简介

 

Mybatis-Plus (简称MP)是 MyBatis 的一个增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生

MyBatis-Plus提供了通用的mapper和service,可以在不编写任何SQL语句的情况下,快速的实现对单表的CRUD、批量、逻辑删除、分页等操作

润物无声

只做增强不做改变,引入它不会对现有工程产生影响,如丝般顺滑

效率至上

只需简单配置,即可快速进行单表CRUD操作,从而节省大量时间

功能丰富

代码生成、自动分页、逻辑删除、自动填充等功能一应俱全

 

特性

 

支持数据库

任何能使用 MyBatis 进行 CRUD, 并且支持标准 SQL 的数据库

 

框架体系

 

1、扫描实体(ScanEntity)

第一步会先扫描当前所操作的实体类,扫描器会通过反射机制对实体类中的属性进行抽取

 

2、分析表与实体类之间的关系

分析表与实体类的关系,实体类中的属性与字段之间的关系

 

3、分析我们当前所调用的方法

根据我们当前所调用的方法生成对应的sql语句,将生成的sql语句注入到mybatis的容器中实现最终的功能

 

实体类简化

Lombok

Lombok官网

Lombok项目是一个java库,它可以自动插入到编辑器和构建工具中,增强java的性能,不需要再写getter、setter或equals方法,只要有一个注解,你的类就有一个功能齐全的构建器、自动记录变量等等

 

 

@NoArgsConstructor注解

生成字节码时自动为实体类生成无参构造

@AllArgsConstructor注解

自动生成全参构造

@Data

整合了Getter、Setter、ToString、EqualsAndHashCode、RequiredArgsConstructor注解

@Getter

快速构建Getter方法

@Setter

快速构建Setter方法

@ToString

快速将当前对象转换成字符串类型,便于log

@EqualsAndHashCode

快速进行相等判断

 

实体类与表的匹配关系

设置表名

@TableName注解

创建实体时我们使用的主键是Long类型,数据库表主键字段是BigInt类型

是因为mybatisPlus使用的主键id是用雪花算法生成的

在mybatisPlus执行查询的时候指定实体匹配的表名

使用全局配置

设置实体类所对应表的统一前缀

 

设置主键

@TableId注解

设置实体类中的指定属性对应的字段为主键id

注解中的value属性可以设置当前属性所对应的表中的字段名

type属性

指定主键的生成方法,默认使用雪花算法IdType.ASSIGN_ID

如果要指定自动递增,首先表中的主键也必须是自动递增的

需要把type属性指定为IdType.AUTO

设置统一的主键生成策略

 

雪花算法

背景

数据库分表

 

单表数据拆分有两种方式:垂直分表和水平分表

 

垂直分表

垂直分表适合将表中某些不常用且占了大量空间的列拆分出去

 

水平分表

主键自增

优点:可以随着数据的增加平滑地扩充新的表

例如,现在的用户是 100 万,如果增加到 1000 万, 只需要增加新的表就可以了,原有的数据不需要动

 

取模

优点:表分布比较均匀

缺点:扩充新的表很麻烦,所有数据都要重分布

 

雪花算法

雪花算法是由Twitter公布的分布式主键生成算法,它能够保证不同表的主键的不重复性,以及相同表的主键的有序性

 

 

优点:整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞,并且效率较高

 

 

设置字段名

@TableField注解

指定属性所对应的字段名,value值为指定的表中的字段名

 

 

逻辑删除

@TableLogic注解

此字段需要有默认值

比如未删除状态字段值默认值为0

delete语句会变成修改操作,会将删除状态字段数值改变为1

下次执行查询就无法查询到删除状态字段数值为1的数据

 

BaseMapper

MyBatis-Plus中的基本增删改查在内置的BaseMapper类中都已得到了实现,我们可以直接使用

我们在让Mapper接口继承BaseMapper类的时候需要提供一个实体类的泛型

 

在springboot启动类中开启映射包扫描

如果基于springboot开发,我们需要指定mapper接口所在的包以及mapper映射文件所在的路径

@MapperScan 用于扫描指定包下的mapper接口

将mapper包下由mybatis动态生成的接口代理类交由spring容器管理

 

 

测试单元,测试是否能查询到数据

表和实体的名字需要相同才能被匹配到

关于Autowired报错,其实是idea编译器在检测时以为接口实例还没被创建出来,在运行时是不会报错的

 

mybatis中内置的显示sql日志

 

insert语句

 

 

删除语句

根据id删除数据

 

根据map集合提供的条件删除数据

 

根据多个id条件删除数据

deleteBatchIds()这个方法使用的是sql中的in()函数

 

修改语句

根据id修改用户数据

 

查询方法

通过id来查询用户信息

根据多个id来查询用户信息

根据Map集合中的内容查询

 

mybatisPlus中自定义sql

需要创建mapper文件

不配置,默认是类路径下的mapper文件,此文件下的所有xml都会被当作映射文件

 

 

Service CRUD接口

通用 Service CRUD 封装IService接口,进一步封装 CRUD 采用 get 查询单行 remove 删除 list 查询集合 page 分页 前缀命名方式区分 Mapper 层避免混淆

MyBatis-Plus中有一个接口 IService和其实现类 ServiceImpl封装了常见的业务层逻辑

 

我们通常会选择创建一个Service接口来继承mybatisPlus的IService接口

 

我们在使用自己的service实现类的时候想要使用IService接口中的方法,但是有些方法我们又不想去重写,因此我们只需要继承一个IService提供的实现类即可

注意需要传入两个泛型,一个是当前类的父接口以及需要被操作的实体类

 

service接口查询总记录数

 

批量添加SQL

底层通过baseMapper中的单个添加的sql语句循环来实现的

 

 

Wapper介绍

删除用的是QueryWrapper

 

QueryWrapper

查询wrapper测试

 

排序的方法

 

删除wrapper测试

因为设置了逻辑删除,此测试实际上是将删除状态从0变为了1

 

修改wrapper测试

第一个user对象是存放需要修改的信息,第二个wrapper是修改条件

 

优先条件设置

在and方法中使用lambda表达式

 

指定需要查询的字段

 

子查询

 

updateWrapper

同时设置修改条件与修改字段

 

组装条件生产sql语句

此方法需要用if语句判断较为麻烦

 

与上面的代码实现相同,但是更加简洁

 

lambdaWrapper

LambdaQueryWrapper

能够防止字段名写错,此方法使用函数式接口,mybatis-plus会自动去匹配对应的字段

 

分页插件

MyBatis Plus自带分页插件,只要简单的配置即可实现分页功能

需要创建一个spring核心配置类

 

测试分页

 

自定义查询分页

接口中定义方法

@Param注解 为参数命名,通过OGNL表达式获取

Page对象必须在参数第一个位置

 

测试

 

乐观锁

场景

一件商品,成本价是80元,售价是100元。

老板先是通知小李,说你去把商品价格增加50元。小 李正在玩游戏,耽搁了一个小时。正好一个小时后,老板觉得商品价格增加到150元,价格太 高,可能会影响销量。又通知小王,你把商品价格降低30元。

此时,小李和小王同时操作商品后台系统。小李操作的时候,系统先取出商品价格100元;小王 也在操作,取出的商品价格也是100元。小李将价格加了50元,并将100+50=150元存入了数据 库;小王将商品减了30元,并将100-30=70元存入了数据库。是的,如果没有锁,小李的操作就 完全被小王的覆盖了。

现在商品价格是70元,比成本价低10元。几分钟后,这个商品很快出售了1千多件商品,老板亏1万多。

乐观锁与悲观锁

乐观锁

上面的故事,如果是乐观锁,小王保存价格前,会检查下价格是否被人修改过了。如果被修改过 了,则重新取出的被修改后的价格,150元,这样他会将120元存入数据库

悲观锁

如果是悲观锁,小李取出数据后,小王只能等小李操作完之后,才能对价格进行操作,也会保证最终的价格是120元。

 

 

乐观锁实现流程

数据库中添加version字段

取出记录时,获取当前version

更新时,version + 1,如果where语句中的version版本不对,则更新失败

 

Mybatis-Plus实现乐观锁

修改实体类

为version字段添加@Version注解 标识乐观锁版本号字段

 

在spring核心配置类中的MybatisPlusInterceptor拦截器中配置

在之前的分页插件之后继续配置

 

因为乐观锁版本号改变而导致的操作失败如何解决?

 

通用枚举

需要在配置文件中设置扫描通用枚举包

需要传入通用枚举类型送在包

设置性别枚举类型

@EnumValue注解 将此注解标注的枚举类型属性值存入数据库中

 

测试