MyBatis Plus提供了分页插件PaginationInterceptor、执行分析插件SqlExplainInterceptor、性能分析插件PerformanceInterceptor以及乐观锁插件OptimisticLockerInterceptor。
Mybatis 通过插件 (Interceptor) 可以做到拦截四大对象相关方法的执行 ,根据需求完成相关数据的动态改变。
四大对象是:
- Executor(拦截执?器的?法)
- StatementHandler(拦截 Sql 语法构建的处理)
- ParameterHandler(拦截参数的处理)
- ResultSetHandler(拦截结果集的处理)
1、分页插件
分页插件,全类名是
com.baomidou.mybatisplus.plugins.PaginationInterceptor,用于支持查询分页功能。可以设置参数,如最大单页限制数量等。
SpringBoot 配置:
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
xml ?式:
2、执行分析插件
SQL执行分析拦截器,全类名是
com.baomidou.mybatisplus.plugins.SqlExplainInterceptor,只支持 MySQL5.6.3以上版本。该插件的作用是分析 DELETE和UPDATE语句 ,防止小白或者恶意进行全表更新、删除操作,不建议在生产环境中使用会造成性能下降,在插件的底层通过SQL语句分析命令 Explain 分析当前的 SQL语句,根据结果集中的 Extra列来断定当前是否全表操作。
SpringBoot 配置:
@Bean
public SqlExplainInterceptor sqlExplainInterceptor() {
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
List sqlParserList = new ArrayList<>();
// 攻击 SQL 阻断解析器、加?解析链
sqlParserList.add(new BlockAttackSqlParser());
sqlExplainInterceptor.setSqlParserList(sqlParserList);
return sqlExplainInterceptor;
}
xml ?式:
3、性能分析插件
性能分析拦截器,全类名是
com.baomidou.mybatisplus.plugins.PerformanceInterceptor,用于输出每条 SQL 语句及其执行时间。SQL性能执行分析 ,开发环境使用超过指定时间,停止运行。
SpringBoot 配置:
@Bean
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(100);
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
xml ?式:
4、乐观锁插件
全类名是
com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor。如果想实现如下需求 : 当要更新一条记录的时候,希望这条记录没有被别人更新,就可以使用该插件进行判断。
乐观锁的实现原理(@Version 用于注解实体字段,必须要有) :
- 取出记录时,获取当前 version
- 更新时,带上这个version
- 执行更新时,set version = yourVersion+1 where version = yourVersion
- 如果 version不对,就更新失败
4.1、插件配置
SpringBoot 配置:
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
xml ?式:
4.2、注解实体字段
需要为实体字段添加 @Version 注解。
第?步,为表添加 version 字段,并且设置初始值为 1 :
ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL AFTER `email`;
UPDATE `tb_user` SET `version`='1';
第?步,为User实体对象添加version字段,并且添加@Version注解:
@Version
private Integer version;
4.3 测试用例
@Test
public void testUpdateVersion(){
User user = new User();
user.setAge(30);
user.setId(2L);
user.setVersion(1); //获取到version为1
int result = this.userMapper.updateById(user);
System.out.println("result = " + result);
}
更新前:
更新后:
4.4、特别说明
- ?持的数据类型只有:int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅?持 updateById(id) 与 update(entity, wrapper) ?法
- 在 update(entity, wrapper) ?法下, wrapper 不能复?!
5、自定义拦截器
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
@Intercepts({@Signature(
type = Executor.class,
method = "update",
args = {MappedStatement.class, Object.class})})
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//拦截?法,具体业务逻辑编写的位置
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
//创建target对象的代理对象,?的是将当前拦截器加?到该对象中
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
//属性设置
}
}
注?到Spring容器:
/**
* ?定义拦截器
*/
@Bean
public MyInterceptor myInterceptor(){
return new MyInterceptor();
}
xml配置: