当前位置:   article > 正文

Mybatis-Plus:插件(mybatis的插件机制、执行分析插件、性能分析插件、乐观锁插件)_mybatis plus 插件

mybatis plus 插件

本节案例承接自上节案例

1. mybatis的插件机制

MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:

  1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
  2. ParameterHandler (getParameterObject, setParameters)
  3. ResultSetHandler (handleResultSets, handleOutputParameters)
  4. StatementHandler (prepare, parameterize, batch, update, query)

总体概括为:

  1. 拦截执行器的方法
  2. 拦截参数的处理
  3. 拦截结果集的处理
  4. 拦截Sql语法构建的处理

我们看到了可以拦截Executor接口的部分方法,比如updatequerycommitrollback等方法,还有其他接口的一些方法等。

拦截器示例:

在这里插入图片描述

MyInterceptor.java

package com.tian.plugins;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;

import java.util.Properties;

@Intercepts({@Signature(	
		// 要拦截的是 Executor 执行器的 update方法
        type = Executor.class,
        method = "update",
        args = {MappedStatement.class, Object.class})})
public class MyInterceptor implements Interceptor {

    @Override
     //拦截方法,具体业务逻辑编写的位置 现在是只有update方法会进入该方法
    public Object intercept(Invocation invocation) throws Throwable {
        return invocation.proceed(); // invocation.proceed()是放行
    }

    @Override
    // 执行sql都会进入该方法 并且会执行4次 因为有4个处理器 
    /*
    1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed) 拦截执行器的方法
	2. ParameterHandler (getParameterObject, setParameters) 拦截参数的处理
	3. ResultSetHandler (handleResultSets, handleOutputParameters) 拦截结果集的处理
	4. StatementHandler (prepare, parameterize, batch, update, query) 拦截Sql语法构建的处理
    */
    public Object plugin(Object target) {
        // 创建target对象的代理对象,目的是将当前拦截器加入到该对象中
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        //属性设置
    }
} 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39

将拦截器注入到Spring容器:

在这里插入图片描述
MybatisPlusConfig.java
在这里插入图片描述

package com.tian.springbootmybatisplus;

import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.tian.plugins.MyInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.tian.mapper") //设置mapper接口的扫描包
public class MybatisPlusConfig {
    @Bean //配置分页插件
    public PaginationInterceptor paginationInterceptor() {
        return new PaginationInterceptor();
    }

    /*** 自定义拦截器 */
    @Bean
    public MyInterceptor myInterceptor() {
        return new MyInterceptor();
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

或者通过xml配置,mybatis-config.xml
在这里插入图片描述


2. 执行分析插件(阻断全表更新、删除的操作)

Mybatis-Plus中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不适用于生产环境。


2.1 配置

在这里插入图片描述

MyInterceptor.java

    @Bean //SQL分析插件
    public SqlExplainInterceptor sqlExplainInterceptor() {

        SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();

        List<ISqlParser> list = new ArrayList<>();
        
        // 攻击 SQL 阻断解析器、加入解析链
        list.add(new BlockAttackSqlParser()); //全表更新、删除的阻断器

        sqlExplainInterceptor.setSqlParserList(list);

        return sqlExplainInterceptor;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

BlockAttackSqlParser.java源码查看
在这里插入图片描述

在这里插入图片描述


2.2 测试

在这里插入图片描述

SpringbootMybatisplusApplicationTests.java

package com.tian.springbootmybatisplus;

import com.tian.mapper.UserMapper;
import com.tian.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringbootMybatisplusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testUpdate() {
        User user = new User();
        user.setAge(20);

        // 把所有人的age设置为20
        int result = this.userMapper.update(user, null);
        System.out.println("result = " + result);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

运行结果:

在这里插入图片描述


3. 性能分析插件

性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常

和执行分析插件一样,该插件只用于开发环境,不建议生产环境使用。

说明:我最开始用的Mybatis-Plus 3.3.2,发现没有PerformanceInterceptor类。于是我把Mybatis-Plus版本降到了 3.1.0 。然后就可以正常使用性能分析插件了。
在这里插入图片描述


3.1 Spring Boot 配置

在这里插入图片描述
MybatisPlusConfig.java

    @Bean
    // SQL 执行性能分析,开发环境使用,线上不推荐。
    public PerformanceInterceptor performanceInterceptor() {
        PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
        // maxTime 指的是 sql 最大执行时长, 单位为ms
        performanceInterceptor.setMaxTime(100);
        // SQL是否格式化 默认为true
        performanceInterceptor.setFormat(true);
        return performanceInterceptor;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

编写测试用例:

在这里插入图片描述

SpringbootMybatisplusApplicationTests.java

package com.tian.springbootmybatisplus;

import com.tian.mapper.UserMapper;
import com.tian.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringbootMybatisplusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testSelectById() {
        User user = new User();
        // 查询Id为2的用户
        user.setId(2L);
        User user1 = user.selectById();
        System.out.println(user1);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

运行结果:

在这里插入图片描述

异常情况补充:

在这里插入图片描述


3.2 配置文件方式配置

上面一直使用的代码注入Bean的方式去配置,现在我们来尝试着使用配置文件的方式去配置,这样可以练练手。
在这里插入图片描述

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.extension.plugins.PerformanceInterceptor">
            <!--最大的执行时间,单位为毫秒-->
            <property name="maxTime" value="100"/>
            <!--对输出的SQL做格式化,默认为false-->
            <property name="format" value="true"/>
        </plugin>
    </plugins>
</configuration>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

然后在SpringBoot的全局配置文件指定Mybatis的配置文件即可:
在这里插入图片描述
application.properties
在这里插入图片描述

# 指定全局的配置文件
mybatis-plus.config-location=classpath:mybatis-config.xml
  • 1
  • 2

4. 乐观锁插件

当要更新一条记录的时候,希望这条记录没有被别人更新

乐观锁实现方式:

  1. 取出记录时,获取当前version
  2. 更新时,带上这个version
  3. 执行更新时, set version = newVersion where version = oldVersion
  4. 如果version不对,就更新失败

4.1 插件配置

配置文件方式:

在这里插入图片描述

  <!--乐观锁插件-->
        <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
  • 1
  • 2

spring boot代码注入Bean的方式:

在这里插入图片描述
MybatisPlusConfig.java

在这里插入图片描述

    @Bean
    public OptimisticLockerInterceptor optimisticLockerInterceptor() {
        return new OptimisticLockerInterceptor();
    }
  • 1
  • 2
  • 3
  • 4

4.2 注解实体字段

需要为实体字段添加@Version注解。

第一步,为表添加version字段,并且设置初始值为1:

Navicat执行下面的sql语句:

ALTER TABLE `tb_user` ADD COLUMN `version` int(10) NULL AFTER `email`; UPDATE `tb_user` SET `version`='1';
  • 1

在这里插入图片描述

第二步,为User实体对象添加version字段,并且添加@Version注解:

在这里插入图片描述


4.3 测试

在这里插入图片描述

SpringbootMybatisplusApplicationTests.java

package com.tian.springbootmybatisplus;

import com.tian.mapper.UserMapper;
import com.tian.pojo.User;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
class SpringbootMybatisplusApplicationTests {

    @Autowired
    private UserMapper userMapper;

    @Test
    public void testUpdate() {
        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);
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

运行结果:

生成的SQL语句为:
在这里插入图片描述

  • 可以看到,更新的条件中有version条件,并且更新的version为2。
  • 如果再次执行,更新则不成功。这样就避免了多人同时更新时导致数据的不一致。

4.4 说明

在这里插入图片描述



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/364177
推荐阅读
相关标签
  

闽ICP备14008679号