【MyBatis-Plus-In-Action】七、外掛拓展
上一節我們學習了mybatis-plus
的程式碼生成器
,這一節我們來學習一下mybatis-plus
的外掛拓展
。
首先我們來複習一下Mybatis 外掛機制:
- 外掛機制: Mybatis 通過外掛(Interceptor) 可以做到攔截四大物件相關方法的執行,根據需求, 完成相關資料的動態改變。 Executor StatementHandler ParameterHandler ResultSetHandler
- 外掛原理: 四大物件的每個物件在建立時,都會執行 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("[email protected]");
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注入
的學習了。
原始碼
相關示例完整程式碼:mybatis-plus-in-action