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

  • 相关阅读:
    六大设计原则之依赖倒置原则
    六大设计原则之里氏替换原则
    六大设计原则之单一设计原则
    六、Spring之DI的Bean的作用域
    五、spring之DI循环依赖
    四、spring之DI
    十二 NIO和IO
    十一 Pipe
    十 DatagramChannel
    九 ServerSocketChannel
  • 原文地址:https://www.cnblogs.com/niujifei/p/15340535.html
Copyright © 2020-2023  润新知