一、插件扩展
1、Mybatis插件机制简介
(1)插件机制
Mybatis 通过插件(Interceptor) 可以做到拦截四大对象相关方法的执行,根据需求,完成相关数据的动态改变。
- Executor
- StatementHandler
- ParameterHandler
- ResultSetHandler
(2)插件原理
四大对象的每个对象在创建时,都会执行interceptorChain.pluginAll(),会经过每个插件对象的plugin()方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四大对象相关方法的执行,因为要执行四大对象的方法需要经过代理
想了解底层,可以通过“StatementHandler“,ctrl+n查看
(3)分页插件
com.baomidou.mybatisplus.plugins.PaginationInterceptor
第一种方式,可以通过xml文件【mybatis-config.xml】方式去注册分页插件,比如:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
<plugins>
<plugin interceptor="com.baomidou.mybatisplus.plugins.PaginationInterceptor "></plugin>
</plugins>
</configuration>
第二种方式,可以通过【applicationContext.xml】方式去注册分页插件,比如:
<property name="plugins">
<list>
<!-- 注册分页插件-->
<bean class="com.baomidou.mybatisplus.plugins.PaginationInterceptor"></bean>
</list>
</property>
(4)编写测试分页插件
package org.apache.test;//package org.apache.test;
import com.baomidou.mybatisplus.plugins.Page;
import org.apache.mybatisplus.beans.Employee;
import org.apache.mybatisplus.mapper.EmployeeMapper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class TestMP03 {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = ctx.getBean("employeeMapper", EmployeeMapper.class);
/**
* 测试分页插件
*/
@Test
public void testPage() {
Page<Employee> page = new Page<>(1, 1);
List<Employee> emps =
employeeMapper.selectPage(page, null);
System.out.println(emps);
}
}
打印输出:说明数据表字段的驼峰命令出现问题
解决方案:由于这个工程是自动生成的,实体类没有对常规的驼峰操作,需要在实体类添含有下划线上添加一个@TableField注解
再去打印输出
2、分页插件需求
2.1、注册分页插件后Page对象的使用
代码实现:
package org.apache.test;//package org.apache.test;
import com.baomidou.mybatisplus.plugins.Page;
import org.apache.mybatisplus.beans.Employee;
import org.apache.mybatisplus.mapper.EmployeeMapper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class TestMP03 {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = ctx.getBean("employeeMapper", EmployeeMapper.class);
/**
* 测试分页插件
*/
@Test
public void testPage() {
Page<Employee> page = new Page<>(1, 1);
List<Employee> emps =
employeeMapper.selectPage(page, null);
System.out.println(emps);
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);
}
}
打印输出:
数据表
2.2、SqlExplainInterceptor 执行分析插件
com.baomidou.mybatisplus.plugins.SqlExplainInterceptor
SQL执行分析拦截器,只支持MySQL5.6.3以上版本
该插件的作用是分析 DELETE UPDATE语句,防止小白 或者恶意进行DELETE UPDATE全表操作
只建议在开发环境中使用,不建议在生产环境使用
在插件的底层 通过SQL语句分析命令:Explain 分析当前的SQL语句, 根据结果集中的Extra列来断定当前是否全表操作
(1)配置执行分析插件
通过【applicationContext.xml】方式去注册执行分析插件
<!-- 执行分析插件-->
<bean class="com.baomidou.mybatisplus.plugins.SqlExplainInterceptor">
<property name="stopProceed" value="true"></property>
</bean>
(2)测试类
package org.apache.test;//package org.apache.test;
import com.baomidou.mybatisplus.plugins.Page;
import org.apache.mybatisplus.beans.Employee;
import org.apache.mybatisplus.mapper.EmployeeMapper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class TestMP03 {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = ctx.getBean("employeeMapper", EmployeeMapper.class);
/**
* 测试SQL执行分析插件
*/
@Test
public void testSQLExplain() {
employeeMapper.delete(null); // 全表删除
}
}
执行发现出现问题
Error: Full table operation is prohibited. SQL: DELETE FROM tbl_employee
解决思路分析
在mysql执行EXPLAIN语句
EXPLAIN DELETE FROM tbl_employee
如图所示:
当我们按条件去执行,如id为100
EXPLAIN DELETE FROM tbl_employee WHERE id=100
2.3、PerformanceInterceptor性能分析插件
com.baomidou.mybatisplus.plugins.PerformanceInterceptor
性能分析拦截器,用于输出每条 SQL 语句及其执行时间
SQL性能执行分析,开发环境使用,超过指定时间,停止运行。有助于发现问题
(1)通过【applicationContext.xml】方式去注册性能分析插件
<!-- 注册性能分析插件 -->
<bean class="com.baomidou.mybatisplus.plugins.PerformanceInterceptor">
<property name="format" value="true"></property>
<!-- <property name="maxTime" value="5"></property> -->
</bean>
(2)测试类
package org.apache.test;//package org.apache.test;
import com.baomidou.mybatisplus.plugins.Page;
import org.apache.mybatisplus.beans.Employee;
import org.apache.mybatisplus.mapper.EmployeeMapper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class TestMP03 {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = ctx.getBean("employeeMapper", EmployeeMapper.class);
/**
* 测试 性能分析插件
*/
@Test
public void testPerformance() {
Employee employee = new Employee();
employee.setLastName("玛利亚老师");
employee.setEmail("mly@sina.com");
employee.setGender("0");
employee.setAge(22);
employeeMapper.insert(employee);
}
}
控制台打印输出
当如果限制时间返回,比:不能超过5ms,超过就不能再执行
再次打印输出
2.4、OptimisticLockerInterceptor乐观锁插件
com.baomidou.mybatisplus.plugins.OptimisticLockerInterceptor
如果想实现如下需求: 当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁的实现原理:
取出记录时,获取当前version 2 更新时,
带上这个version 2 执行更新时, set version = yourVersion+1 where version = yourVersion
如果version不对,就更新失败
@Version 用于注解实体字段,必须要有
(1)修改实体类【添加version属性】
(2)修改数据表字段、并添加数据
(3)测试类
package org.apache.test;//package org.apache.test;
import com.baomidou.mybatisplus.plugins.Page;
import org.apache.mybatisplus.beans.Employee;
import org.apache.mybatisplus.mapper.EmployeeMapper;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class TestMP03 {
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
EmployeeMapper employeeMapper = ctx.getBean("employeeMapper", EmployeeMapper.class);
/**
* 测试 乐观锁插件
*/
@Test
public void testOptimisticLocker() {
//更新操作
Employee employee = new Employee();
employee.setId(1);
employee.setLastName("Tom");
employee.setEmail("tomAA@sina.com");
employee.setGender("1");
employee.setAge(22);
employee.setVersion(2);
employeeMapper.updateById(employee);
}
}
打印输出
更新后的数据表