一、MyBatis 插件机制简介
1、插件机制
MyBatis 通过插件(Interceptor)可以做到四大对象相关方法的执行,根据需求,完成相关数据的动态改变。
四大对象
Executor
StatementHandler
ParameterHandler
ResultSetHandler
2、插件原理
四大对象的每个对象在创建时,都会执行 Interceptor.pluginAll(),会经过每个插件对象的 plugin() 方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四大对象相关方法的执行,因为要执行四大对象的方法需要经过代理。
二、分页插件
com.baomidou.mybatisplus.plugins.PaginationInterceptor
注册插件:
方式一:在MyBatis的配置文件中注册
<plugins>
<plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></plugin>
</plugins>
方式二:在Spring管理的 sessionFactoryBean 中进行配置
<bean id="sessionFactoryBean" class="com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.njf.mp.bean"/>
<property name="typeAliases">
<array>
<value>com.njf.mp.bean.Employee</value>
</array>
</property>
<!-- configLocation 指定全局配置文件的位置-->
<property name="configLocation" value="classpath:mybatis-config.xml" />
<!-- 指定mapper 文件的位置 -->
<!--<property name="mapperLocations" value="classpath:mybatis/mapper/*.xml"/>-->
<!-- 注入全局MP策略配置 -->
<property name="globalConfig" ref="globalConfig"/>
<!--插件注册-->
<property name="plugins">
<list>
<!-- 注册分页插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
</list>
</property>
</bean>
测试:
/**
* 测试分页插件
* SQL 语句
* Preparing: SELECT id AS id,last_name AS lastName,email,gender,age FROM tbl_employee LIMIT 0,2
*/
@Test
public void testPage() {
Page<Employee> page = new Page<>(1, 2);
List<Employee> emps = employeeMapper.selectPage(page, null);
emps.forEach(System.out::println);
System.out.println("----------------获取分页相关的一些信息-------------------------");
System.out.println("总条数" + page.getTotal());
System.out.println("当前页码" + page.getCurrent());
System.out.println("总页码" + page.getPages());
System.out.println("每页显示的条数" + page.getSize());
System.out.println("是否有上一页" + page.hasPrevious());
System.out.println("是否有下一页" + page.hasNext());
//将查询的结果封装到 page 对象中
page.setRecords(emps);
}
三、执行分析插件
(1)com.baomidou.mybatisplus.plugins.SqlExplainInterceptor
(2)SQL 执行分析拦截器,只支持 MySQL5.6.3 以上版本;
(3)该插件的作用是分析 DELETE UPDATE语句,防止小白或者恶意进行 DELETE UPDATE 全表操作;
(4)只建议在开发环境中使用,不建议在生产环境使用;
(5)在插件的底层通过 SQL 语句分析命令:explain 分析当前的 SQL 语句,根据结果集中的 Extra 列来判断是否全表操作;
注册插件:
<!-- 注册执行分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<property name="stopProceed" value="true"></property> //设置为 true,如果是对全表的删除或更新操作会停止当前操作
</bean>
测试:
/**
* 测试 SQL执行分析插件
*/
@Test
public void testSqlExplain() {
employeeMapper.delete(null); //全表删除
}
执行原理:
当执行的时候是全表的操作,并且设置了 stopProceed() 属性,就会抛出异常中断操作。
四、性能分析插件
(1)com.baomidou.mybatisplus.plugins.PerformanceInterceptor;
(2)性能分析拦截器,用于输出每条 SQL 语句及其执行时间;
(3)SQL 性能执行分析,开发环境使用,超过指定时间,停止运行,有助于发现问题;
注册插件:
<!-- 性能分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
<!--格式化SQL-->
<property name="format" value="true"></property>
<!--指定SQL最大执行时间-->
<property name="maxTime" value="100"></property>
</bean>
测试:
/**
* 测试 SQL 性能分析插件
*/
@Test
public void testPerformance() {
Employee employee = new Employee();
employee.setLastName("小泽老师");
employee.setEmail("xz@sina.com");
employee.setGender(0);
employee.setAge(22);
employeeMapper.insert(employee);
}
运行结果:
可以看到整个SQL的执行语句和消耗时间。
如果设置了SQL执行最大时间,当执行超时就会阻断执行。
五、乐观锁插件
(1)com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor;
(2)如果想实现如下需求:当要更新一条记录时候,希望这条记录没有被别人更新;
(3)乐观锁的实现原理:
取出记录时,获取当前 version 2
更新时,带上这个 version 2
执行更新时,set version = yourVersion + 1 where version = yourVersion
如果 version 不对,就更新失败
(4)@Version 用于注解实体字段,必须要有;
注册插件:
<bean class="com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor"></bean>
在实体上面添加字段和注解:
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(value = "last_name")
private String lastName;
private String email;
private Integer gender;
private Integer age;
@TableField(exist = false)
private Double salary;
@Version
private int version;
测试代码:
/**
* 测试乐观锁
* SQL 语句:
* Preparing: UPDATE tbl_employee SET last_name=?, email=?, age=?, version=? WHERE id=? and version=?
* Parameters: Tom(String), tom@126.com(String), 22(Integer), 2(Integer), 14(Integer), 1(Integer)
*/
@Test
public void testOptimisticLocker() {
//更新操作
Employee employee = new Employee();
employee.setId(14);
employee.setLastName("Tom");
employee.setEmail("tom@126.com");
employee.setAge(22);
employee.setVersion(1);
employeeMapper.updateById(employee);
}
执行更新操作时,会用设置的 version 与 数据库的 version 对比,如果都一致了才进行更新。
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· 没有源码,如何修改代码逻辑?
· NetPad:一个.NET开源、跨平台的C#编辑器
2019-09-26 事务
2019-09-26 多表查询(内连接与外连接)
2019-09-26 栈实现综合计算器(中缀表达式)
2019-09-26 数组模拟栈
2019-09-26 栈 Stack