1 Mybatis插件机制
Mybatis插件是对 Executor、StatementHandler、ParameterHandler、ResultSetHandler 这四个接口上的方法进行拦截,利用JDK动态代理机制,为这些接口的实现类创建代理对象,在执行方法时,先去执行代理对象的方法,从而执行自己编写的拦截逻辑。
- Executor
MyBatis的内部执行器,负责调用StatementHandler操作数据库,并把结果集通过ResultSetHandler进行自动映射。
- StatementHandler
MyBatis直接调用数据库执行SQL脚本的对象。
- ParameterHandler
MyBatis实现SQL入参设置的对象。
- ResultSetHandler
MyBatis把ResultSet集合映射成POJO的接口对象。
2 MybatisPlus常用插件
MybatisPlus依据Mybatis插件机制,为我们提供了更多工作中常用的插件。
常用插件,以下插件均实现了 InnerInterceptor
接口:
- 自动分页
PaginationInnerInterceptor
- 防止全表更新与删除
BlockAttackInnerInterceptor
- 乐观锁
OptimisticLockerInnerInterceptor
3 分页插件
在之前使用 mapper模式 及 ActiveRecord 模式进行分页查询时,都使用了配置类中配置分页插件的方式,实现分页查询功能。
首先根据查询条件,查询出所有符合条件的记录总数;
==> Preparing: SELECT COUNT(*) AS total FROM user WHERE (remark LIKE ?)
==> Parameters: %老师%(String)
<== Columns: total
<== Row: 5
<== Total: 1
然后根据开发人员在程序中设置的分页条件,在 SQL 语句末尾使用 limit 语句实现分页查询。
==> Preparing: SELECT id,username,gendar,remark FROM user WHERE (remark LIKE ?) LIMIT ?,?
==> Parameters: %老师%(String), 2(Long), 2(Long)
<== Columns: id, username, gendar, remark
<== Row: 10, 张三, 女, 体育老师
<== Row: 11, 刘能, 男, 演讲老师
<== Total: 2
4 防止全表更新与删除插件
插件的作用:
分析删除和更新语句,防止因误操作而对全表进行更新或删除制作。
在配置类或启动类中,配置防止全表更新及删除插件。
创建测试方法验证效果,删除全表所有记录:
程序执行后报错如下,全表删除失败:
5 乐观锁插件
5.1 什么是锁
我们在对数据库中的数据进行修改时,为了避免被多人同时修改,最佳的处理办法是对该条数据进行加锁从而防止被并行访问。
5.2 锁的分类
- 悲观锁
悲观锁是对数据被外界修改持保守态度。在整个数据处理过程当中,将数据处于锁定状态。通常依靠数据库提供的锁机制。
A/B用户同时访问数据表同一条记录时,如果A先到,数据将被锁定,A访问结束后B才能访问数据并进行相应操作。
- 乐观锁
在访问数据时,并不会进行限制,只有在数据进行提交更新时,才会正式对数据的冲突进行检测,如果冲突,就会返回异常信息。
A/B用户同时访问数据表同一条记录时,不会锁定数据,如果A先提交修改后,B再进行提交,此时会对数据进行冲突检测,如果B提交的修改比当前最新数据老,则不允许提交。
5.3 MybatisPlus乐观锁插件
5.3.1 实现方式
从数据库取出记录时,获取当前数据的版本;
执行更新时,会对原来读取的版本与数据当前版本进行比较,如果一致就执行更新;
更新成功后,数据版本号增加。
5.3.2 设置乐观锁
在配置类中添加乐观锁
5.3.3 修改数据表
因乐观锁中使用了版本即 version 字段,需要修改数据表,在其中添加 version 字段,并设置默认值0:
5.3.4 修改实体类
在实体类中,增加 version字段,并使用注解 @Version 修饰:
5.3.5 乐观锁测试
在修改数据时,需要设置version值,该值需要与数据库中version字段值一致才能更新成功。
执行后在控制台可以看到输出如下内容
==> Preparing: UPDATE user SET username=?, version=? WHERE id=? AND version=?
==> Parameters: 赵敏(String), 1(Integer), 12(Integer), 0(Integer)
<== Updates: 1
数据更新成功后,version值自增。
需要注意的是:
如果不对version进行显示设置时,该值默认为0,如果此时数据库中的version字段大于0,更新操作将执行失败;
如果对version字段的设置,与数据库中对应记录的version字段数值不一致,也会更新失败。
我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!