MyBatisPlus 之 插件扩展

一、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 对比,如果都一致了才进行更新。

原文地址:https://www.cnblogs.com/niujifei/p/15340535.html