转载

七、插件拓展

上一节我们学习了 mybatis-plus代码生成器 ,这一节我们来学习一下 mybatis-plus插件拓展

首先我们来复习一下Mybatis 插件机制:

  1. 插件机制: Mybatis 通过插件(Interceptor) 可以做到拦截四大对象相关方法的执行,根据需求, 完成相关数据的动态改变。 Executor StatementHandler ParameterHandler ResultSetHandler
  2. 插件原理: 四大对象的每个对象在创建时,都会执行 interceptorChain.pluginAll(),会经过每个插件对象的 plugin()方法,目的是为当前的四大对象创建代理。代理对象就可以拦截到四大对象相关方法的执行,因为要执行四大对象的方法需要经过代理。

我们在 mybatis-plus 这里学习三个插件,其他的插件看官可以自己自行尝试:

  • 分页插件
  • 执行分析插件
  • 乐观锁插件

首先按照 快速开始——Spring集成Mybatis-Plus 一节的操作,新建一个 mp06 的  Module ,可以将 mp05 中的内容全部复制过来。

修改mp06的pom.xml文件:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>mybatis-plus-in-action</artifactId>
        <groupId>com.demo.mybatis-plus</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>mp06</artifactId>

    <dependencies>
        <!-- mp 依赖
            mybatis-plus 会自动维护mybatis 以及 mybatis-spring相关的依赖
            Mybatis 及 Mybatis-Spring 依赖请勿加入项目配置,以免引起版本冲突!!!Mybatis-Plus 会自动帮你维护!
         -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus</artifactId>
            <version>${mybatis.plus.version}</version>
        </dependency>
        <!--junit -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
        </dependency>
        <!-- log4j -->
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>${log4j.version}</version>
        </dependency>
        <!-- druid -->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>${druid.version}</version>
        </dependency>
        <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>${mysql.version}</version>
        </dependency>
        <!-- spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-orm</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>${lombok.version}</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${spring.version}</version>
        </dependency>
        <!--注意: MyBatis-Plus 从 3.0.3 之后移除了代码生成器与模板引擎的默认依赖,需要手动添加相关依赖: -->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-generator</artifactId>
            <version>${mybatis.plus.version}</version>
        </dependency>
        <!--模板引擎
        MP 的代码生成器默认使用的是 Apache 的 Velocity 模板,当然也可以更换为别的模板
        技术,例如 freemarker。此处不做过多的介绍。
        需要加入 Apache Velocity 的依赖-->
        <dependency>
            <groupId>org.apache.velocity</groupId>
            <artifactId>velocity-engine-core</artifactId>
            <version>${velocity.version}</version>
        </dependency>
        <!--加入 slf4j ,查看日志输出信息-->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${slf4j.version}</version>
        </dependency>
    </dependencies>
</project>
复制代码

下面我们需要根据不同的插件做的一些修改:

1、分页插件

其实在之前的分页查询代码示例中,我们已经展示了分页插件,不过当时并没有介绍,现在我们来详细介绍一下。

我们有两种配置方式可以实现分页的功能:

1.1、修改mybatis-config.xml文件,添加分页插件

<!-- 1、第一种方式,在 mybatis-config.xml 文件中引入分页插件-->
<plugins>
    <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></plugin>
</plugins>
复制代码

完整 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>

    <!-- 1、第一种方式,在 mybatis-config.xml 文件中引入分页插件-->
    <plugins>
        <plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor"></plugin>
    </plugins>

</configuration>
复制代码

1.2、修改applicationContext.xml文件,添加分页插件

sqlSessionFactory 这个bean中,通过 <property name="plugins"> 配置插件,接下来的所有插件都配置在这个list中

<!-- 2、第二种方式,在 applicationContext.xml 文件中引入分页插件-->
<property name="plugins">
    <list>
        <!-- 分页查询插件 -->
        <bean id="paginationInterceptor"
              class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor">
            <property name="dialectType" value="mysql"/>
        </bean>
    </list>
</property>
复制代码

1.3、测试分页插件

1.1和1.2的方式选择哪一种都可以实现分页的功能,现在我们在 TestMp 测试类中添加下面代码,来测试分页插件的功能

/**
* 测试分页插件
*/
@Test
public void testPage() {
    IPage<Employee> employeeIPage = employeeMapper.selectPage(new Page<>(2, 1), null);
    System.out.println("employeeIPage:" + employeeIPage.getRecords());
}
复制代码

2、执行分析插件

该插件的作用是分析 DELETE UPDATE 语句,防止小白或者恶意进行 DELETE UPDATE 全表操作 。在插件的底层 通过 SQL 语句分析命令:Explain 分析当前的 SQL 语句, 根据结果集中的 Extra 列来断定当前是否全表操作。

注意 :只建议在开发环境中使用,不建议在生产环境使用 。SQL 执行分析拦截器,只支持 MySQL5.6.3 以上版本 。

2.2、修改applicationContext.xml文件,添加执行分析插件

<!-- 执行分析插件 只建议在开发环境中使用,不建议在生产环境使用 -->
<bean class="com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor">
    <property name="sqlParserList">
        <!-- 禁止全表删除-->
        <bean class="com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser"></bean>
    </property>
</bean>
复制代码

2.2、测试执行分析插件

我们来进行一个全表删除来测试一下我们的执行分析插件,在测试类中添加下面的代码:

/**
* 测试 SQL 执行分析插件
*/
@Test
public void testSqlExplain() {

    // 全表删除
    employeeMapper.delete(null);
}
复制代码

执行该方法后我们会看到测试方法执行失败,提示我们禁止全表的删除:

七、插件拓展

3、乐观锁插件

思考?如果想实现如下需求: 当要更新一条记录的时候,希望这条记录没有被别人更新 。当我们想实现上面的需求的时候,首先想到的是使用乐观锁机制。

乐观锁的实现原理: 1)取出记录时,获取当前 version 2)更新时,带上这个 version 3)执行更新时, set version = yourVersion+1 where version = yourVersion 如果 version 不对,就更新失败

3.1、修改applicationContext.xml文件,添加乐观锁插件

要想使用 Mybatis-Plus 提供的乐观锁插件,首先需要修改applicationContext.xml文件,添加乐观锁插件

<!-- 乐观锁插件,做这个测试的时候,需要给实体类接一个version字段,相应的也需要在数据库中添加该字段 -->
<bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"></bean>
复制代码

3.2、修改Employee实体类

修改Employee实体类,添加 version 字段,并添加getter、setter方法

@Version
private Integer version;

public Integer getVersion() {
    return version;
}

public void setVersion(Integer version) {
    this.version = version;
}
复制代码

3.3、测试乐观锁插件

在测试类中添加下面的代码:

/**
* 测试 乐观锁
*/
@Test
public void testOptimisticLocker() {

    Employee employee = new Employee();
    employee.setId(10);
    employee.setLastName("MP");
    employee.setAge(25);
    employee.setEmail("mp@qq.com");
    employee.setGender("0");
    employee.setVersion(2);

![mp06-02.png](https://upload-images.jianshu.io/upload_images/19878305-e8348cc75321c5f1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
    employeeMapper.updateById(employee);
}
复制代码

执行该方法后我们会看到测试方法执行成功,更新时,带上这个 version,但更新的数据为0条,表示数据库中的数据并没有被更新,注意看我们的更新代码:

七、插件拓展

完成上面的操作后,mp06的完整 applicationContext.xml 文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
       xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring
        http://mybatis.org/schema/mybatis-spring-1.2.xsd
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-4.0.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-4.0.xsd">

    <!-- 数据源 -->
    <context:property-placeholder location="classpath:db.properties"/>
    <bean id="dataSource"
          class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"></property>
        <property name="password" value="${jdbc.password}"></property>
    </bean>

    <!-- 事务管理器 -->
    <bean id="dataSourceTransactionManager"
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 基于注解的事务管理 -->
    <tx:annotation-driven
            transaction-manager="dataSourceTransactionManager"/>

    <!-- 配置 SqlSessionFactoryBean
        mybatis提供的:org.mybatis.spring.SqlSessionFactoryBean
        mybatis-plus提供的:3.2.0 com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean
                2.3 com.baomidou.mybatisplus.spring.MybatisSqlSessionFactoryBean
     -->
    <bean id="sqlSessionFactoryBean"
          class="com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean">
        <!-- 数据源 -->
        <property name="dataSource" ref="dataSource"></property>
        <property name="configLocation" value="classpath:mybatis-config.xml"></property>
        <!-- 别名处理 -->
        <property name="typeAliasesPackage" value="com.mp.beans"></property>
        <!-- 注入配置-->
        <!--<property name="configuration" ref="configuration"></property>-->
        <!-- 注入全局配置策略-->
        <property name="globalConfig" ref="globalConfiguration"></property>

        <!-- 2、第二种方式,在 applicationContext.xml 文件中引入分页插件-->
        <property name="plugins">
            <list>
                <!-- 分页查询插件 -->
                <bean id="paginationInterceptor"
                      class="com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor">
                    <property name="dialectType" value="mysql"/>
                </bean>

                <!-- 执行分析插件 只建议在开发环境中使用,不建议在生产环境使用 -->
                <bean class="com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor">
                    <property name="sqlParserList">
                            <!-- 禁止全表删除-->
                        <bean class="com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser"></bean>
                    </property>
                </bean>

                <!-- 乐观锁插件,做这个测试的时候,需要给实体类接一个version字段,相应的也需要在数据库中添加该字段 -->
                <bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"></bean>
            </list>
        </property>

    </bean>

    <!--这个等于Mybatis的全局配置文件,如果在MybatisSqlSessionFactoryBean里面已经配置了configLocation属性(外部加载Mybatis全局配置文件),就不能再配置configuration属性-->
    <bean id="configuration" class="com.baomidou.mybatisplus.core.MybatisConfiguration">
        <!--开启驼峰命名-->
        <property name="mapUnderscoreToCamelCase" value="true"/>
        <!--日志打印SQL语句-->
        <property name="logImpl" value="org.apache.ibatis.logging.log4j.Log4jImpl"></property>
    </bean>

    <!-- 定义mybatis-plus全局策略配置-->
    <bean id="globalConfiguration" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
        <!-- 全局主键策略-->
        <property name="dbConfig" ref="dbConfig"></property>
    </bean>
    <!-- 这里-->
    <bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
        <!-- 全局表主键生成策略 -->
        <property name="idType" value="AUTO"></property>
        <!-- 全局的表前缀策略配置 -->
        <property name="tablePrefix" value="tbl_"></property>
    </bean>

    <!--
    配置 mybatis 扫描 mapper 接口的路径
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage"
                  value="com.mp.mapper"></property>
    </bean>
</beans>
复制代码

mp06的代码结构如下所示:

七、插件拓展

至此,基于 mybatis-plus插件拓展 演示就完成了,下面我们就可以进入到下一节 自定义全局操作和全局sql注入 的学习了。

原文  https://juejin.im/post/5db46ed86fb9a0208801fbbb
正文到此结束
Loading...