上一节我们学习了 mybatis-plus
的 代码生成器
,这一节我们来学习一下 mybatis-plus
的 插件拓展
。
首先我们来复习一下Mybatis 插件机制:
我们在 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、第一种方式,在 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> 复制代码
在 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.1和1.2的方式选择哪一种都可以实现分页的功能,现在我们在 TestMp
测试类中添加下面代码,来测试分页插件的功能
/** * 测试分页插件 */ @Test public void testPage() { IPage<Employee> employeeIPage = employeeMapper.selectPage(new Page<>(2, 1), null); System.out.println("employeeIPage:" + employeeIPage.getRecords()); } 复制代码
该插件的作用是分析 DELETE UPDATE 语句,防止小白或者恶意进行 DELETE UPDATE 全表操作 。在插件的底层 通过 SQL 语句分析命令:Explain 分析当前的 SQL 语句, 根据结果集中的 Extra 列来断定当前是否全表操作。
注意
:只建议在开发环境中使用,不建议在生产环境使用 。SQL 执行分析拦截器,只支持 MySQL5.6.3 以上版本 。
<!-- 执行分析插件 只建议在开发环境中使用,不建议在生产环境使用 --> <bean class="com.baomidou.mybatisplus.extension.plugins.SqlExplainInterceptor"> <property name="sqlParserList"> <!-- 禁止全表删除--> <bean class="com.baomidou.mybatisplus.extension.parsers.BlockAttackSqlParser"></bean> </property> </bean> 复制代码
我们来进行一个全表删除来测试一下我们的执行分析插件,在测试类中添加下面的代码:
/** * 测试 SQL 执行分析插件 */ @Test public void testSqlExplain() { // 全表删除 employeeMapper.delete(null); } 复制代码
执行该方法后我们会看到测试方法执行失败,提示我们禁止全表的删除:
思考?如果想实现如下需求: 当要更新一条记录的时候,希望这条记录没有被别人更新 。当我们想实现上面的需求的时候,首先想到的是使用乐观锁机制。
乐观锁的实现原理: 1)取出记录时,获取当前 version 2)更新时,带上这个 version 3)执行更新时, set version = yourVersion+1 where version = yourVersion 如果 version 不对,就更新失败
要想使用 Mybatis-Plus
提供的乐观锁插件,首先需要修改applicationContext.xml文件,添加乐观锁插件
<!-- 乐观锁插件,做这个测试的时候,需要给实体类接一个version字段,相应的也需要在数据库中添加该字段 --> <bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"></bean> 复制代码
修改Employee实体类,添加 version
字段,并添加getter、setter方法
@Version private Integer version; public Integer getVersion() { return version; } public void setVersion(Integer version) { this.version = version; } 复制代码
在测试类中添加下面的代码:
/** * 测试 乐观锁 */ @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注入
的学习了。