8、自定義全局操做和全局sql注入

上一節咱們學習了mybatis-plus 的插件拓展,這一節咱們來學習一下mybatis-plus 的自定義全局操做和全局sql注入java

BaseMapper提供了17個經常使用方法,可是這些方法並不能實現咱們所有的需求,那麼怎麼辦呢?你們確定會想到是在xml文件中寫sql語句解決。這樣確實能夠,由於MP是隻作加強不作改變,咱們徹底能夠按照mybatis的原來的方式來解決。不過MP也提供了另外一種解決辦法,那就是自定義全局操做。所謂自定義全局操做,也就是咱們能夠在mapper中自定義一些方法,而後經過某些操做,讓自定義的這個方法也能像BaseMapper的內置方法,供全局調用。接下來就看看如何實現。mysql

根據MybatisPlus 的 DefaultSqlInjector 和 AbstractMethod 能夠自定義各類你想要的 sql ,注入到全局中,至關於自定義 Mybatisplus 自動注入的方法。以前須要在 xml 中進行配置的 SQL 語句,如今經過擴展 DefaultSqlInjector 和 AbstractMethod在加載 mybatis 環境時就注入。git

實現自定義全局操做和全局sql注入的步驟:github

分別繼承 DefaultSqlInjector 和 AbstractMethod :web

  1. 在 Mapper 接口中定義相關的 CRUD 方法
  2. 擴展 AbstractMethod 的 injectMappedStatement 方法,實現 Mapper 接口中方法要注入的 SQL
  3. 擴展 DefaultSqlInjector ,重寫 getMethodList 方法,添加自定義方法
  4. 修改applicationContext.xml文件,在 MP 全局策略中,配置自定義注入器

看完上邊的理論,可能仍是一臉懵逼,下面咱們來一步步實戰一下:spring

首先按照快速開始——Spring集成Mybatis-Plus一節的操做,新建一個mp07 的 Module,能夠將mp06中的內容所有複製過來。sql

修改mp07的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>mp07</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>
複製代碼

下面是咱們要進行的修改,咱們以實現一個deleteAll方法爲例:apache

一、修改EmployeeMapper

在mapper接口中定義deleteAll()方法api

public interface EmployeeMapper extends BaseMapper<Employee> {
    int deleteAll();
}
複製代碼

注意:這個時候你會發現idea會報錯,由於沒有對應的*mapp.xml文件中有deleteAll方法的聲明,這個咱們能夠忽略它。

二、新建DeleteAll類,繼承AbstractMethod

com.mp.methods路徑下新建一個和EmployeeMapperdeleteAll()方法同名的類DeleteAll,繼承AbstractMethod類並實現 injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) 方法。具體代碼以下:

public class DeleteAll extends AbstractMethod {

    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        /* 執行 SQL ,動態 SQL 參考類 SqlMethod */
        String sql = "delete from " + tableInfo.getTableName();
        /* mapper 接口方法名一致 */
        String method = "deleteAll";
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return this.addDeleteMappedStatement(mapperClass, method, sqlSource);
    }
}
複製代碼

注意:這一步咱們是實現了mapper中對應方法的sql的功能實現。

三、新建MySqlInjector類,繼承DefaultSqlInjector

com.mp.injector路徑下新建一個MySqlInjector類,擴展 DefaultSqlInjector ,重寫 getMethodList 方法,添加自定義方法,將DeleteAll類添加到方法列表中。具體代碼以下:

@Component
public class MySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass);
        //增長自定義方法
        methodList.add(new DeleteAll());
        return methodList;
    }
}
複製代碼

四、修改applicationContext.xml文件,在 MP 全局策略中,配置自定義注入器

注入自定義注入器:

<!-- 注入自定義注入器 -->
<bean name="mysqlInjector" class="com.mp.injector.MySqlInjector"></bean>
複製代碼

將 mysqlInjector 添加到mybatis-plus全局策略配置 globalConfiguration 中:

<!-- 定義mybatis-plus全局策略配置-->
<bean id="globalConfiguration" class="com.baomidou.mybatisplus.core.config.GlobalConfig">
    <!-- 自定義注入器-->
    <property name="sqlInjector" ref="mysqlInjector"></property>
</bean>
複製代碼

再將globalConfiguration 添加到MP的sqlSessionFactoryBean中:

<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="globalConfig" ref="globalConfiguration"></property>
</bean>
複製代碼

完整 applicationContext.xml 文件能夠參考本節末尾相關文件。

五、測試自定義全局操做

修改TestMP測試類,添加testInjector方法:

/**
* 測試自定義全局操做
*/
@Test
public void testInjector(){
    int ret = employeeMapper.deleteAll();
    System.out.println(ret);

}
複製代碼

mp07-01.png

六、自定義注入器的應用——邏輯刪除

假刪除、邏輯刪除: 並不會真正的從數據庫中將數據刪除掉,而是將當前被刪除的這條數據中的一個邏輯刪除字段置爲刪除狀態.。

mybatis-plus中若是要實現邏輯刪除,須要作如下修改:

6.一、修改Employee

在Employee實體類中添加 isDelete 字段,並使用 @TableLogic註解來註釋該字段,同時在對應的表中添加邏輯刪除字段 is_delete

/**
* 邏輯刪除字段 同時在對應的表中添加邏輯刪除字段 is_delete
*/
@TableLogic
private Integer isDelete;
複製代碼

6.二、修改applicationContext.xml文件

在applicationContext.xml文件中添加邏輯刪除配置:

<!-- 配置邏輯刪除全局值-->
<property name="logicDeleteValue" value="-1"></property>
<property name="logicNotDeleteValue" value="1"></property>
複製代碼

上面的配置添加在 com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig 對應的配置中:

<bean id="dbConfig" class="com.baomidou.mybatisplus.core.config.GlobalConfig$DbConfig">
    <!-- 全局表主鍵生成策略 -->
    <property name="idType" value="AUTO"></property>
    <!-- 全局的表前綴策略配置 -->
    <property name="tablePrefix" value="tbl_"></property>

    <!-- 配置邏輯刪除全局值-->
    <property name="logicDeleteValue" value="-1"></property>
    <property name="logicNotDeleteValue" value="1"></property>
</bean>
複製代碼

能夠參考完整 applicationContext.xml 文件,相關文件在本節末尾。

6.三、修改TestMP測試類,添加測試方法

/**
* 測試邏輯刪除
*/
@Test
public void testLogicDeleteById() {
    employeeMapper.deleteById(1);
}
@Test
public void testLogicDeleteBatchIds() {
    employeeMapper.deleteBatchIds(Arrays.asList(15, 16, 17));
}
@Test
public void testLogicDelete() {
    employeeMapper.delete(new QueryWrapper<Employee>().eq("age", 25));
}
複製代碼

完成上面的操做後,mp07的完整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>

        <!-- 二、第二種方式,在 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">-->
<!--                            &lt;!&ndash; 禁止全表刪除&ndash;&gt;-->
<!--                        <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>
        <property name="sqlInjector" ref="mysqlInjector"></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>

        <!-- 配置邏輯刪除全局值-->
        <property name="logicDeleteValue" value="-1"></property>
        <property name="logicNotDeleteValue" value="1"></property>
    </bean>

    <!-- 注入自定義注入器 -->
    <bean name="mysqlInjector" class="com.mp.injector.MySqlInjector"></bean>

    <!--
    配置 mybatis 掃描 mapper 接口的路徑
    -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage"
                  value="com.mp.mapper"></property>
    </bean>
</beans>
複製代碼

mp07的代碼結構以下所示:

mp07-02.png

至此,基於 mybatis-plus 的自定義全局操做和全局sql注入演示就完成了,下面咱們就能夠進入到下一節公共字段自動填充的學習了。

源代碼

相關示例完整代碼:mybatis-plus-in-action

相關文章
相關標籤/搜索