八、自定义全局操作和全局sql注入

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/runewbie/article/details/102759050

上一节我们学习了mybatis-plus 的插件拓展,这一节我们来学习一下mybatis-plus 的自定义全局操作和全局sql注入

BaseMapper提供了17个常用方法,但是这些方法并不能实现我们全部的需求,那么怎么办呢?大家肯定会想到是在xml文件中写sql语句解决。这样确实可以,因为MP是只做增强不做改变,我们完全可以按照mybatis的原来的方式来解决。不过MP也提供了另一种解决办法,那就是自定义全局操作。所谓自定义全局操作,也就是我们可以在mapper中自定义一些方法,然后通过某些操作,让自定义的这个方法也能像BaseMapper的内置方法,供全局调用。接下来就看看如何实现。

根据MybatisPlus 的 DefaultSqlInjector 和 AbstractMethod 可以自定义各种你想要的 sql ,注入到全局中,相当于自定义 Mybatisplus 自动注入的方法。之前需要在 xml 中进行配置的 SQL 语句,现在通过扩展 DefaultSqlInjector 和 AbstractMethod在加载 mybatis 环境时就注入。

实现自定义全局操作和全局sql注入的步骤:

分别继承 DefaultSqlInjector 和 AbstractMethod :

  1. 在 Mapper 接口中定义相关的 CRUD 方法
  2. 扩展 AbstractMethod 的 injectMappedStatement 方法,实现 Mapper 接口中方法要注入的 SQL
  3. 扩展 DefaultSqlInjector ,重写 getMethodList 方法,添加自定义方法
  4. 修改applicationContext.xml文件,在 MP 全局策略中,配置自定义注入器

看完上边的理论,可能还是一脸懵逼,下面我们来一步步实战一下:

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

修改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方法为例:

1、修改EmployeeMapper

在mapper接口中定义deleteAll()方法

public interface EmployeeMapper extends BaseMapper<Employee> {
    int deleteAll();
}

注意:这个时候你会发现idea会报错,因为没有对应的*mapp.xml文件中有deleteAll方法的声明,这个我们可以忽略它。

2、新建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的功能实现。

3、新建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;
    }
}

4、修改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 文件可以参考本节末尾相关文件。

5、测试自定义全局操作

修改TestMP测试类,添加testInjector方法:

/**
* 测试自定义全局操作
*/
@Test
public void testInjector(){
    int ret = employeeMapper.deleteAll();
    System.out.println(ret);

}

mp07-01.png

6、自定义注入器的应用——逻辑删除

假删除、逻辑删除: 并不会真正的从数据库中将数据删除掉,而是将当前被删除的这条数据中的一个逻辑删除字段置为删除状态.。

mybatis-plus中如果要实现逻辑删除,需要做以下修改:

6.1、修改Employee

在Employee实体类中添加 isDelete 字段,并使用 @TableLogic注解来注释该字段,同时在对应的表中添加逻辑删除字段 is_delete

/**
* 逻辑删除字段 同时在对应的表中添加逻辑删除字段 is_delete
*/
@TableLogic
private Integer isDelete;

6.2、修改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.3、修改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>

        <!-- 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">-->
<!--                            &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

猜你喜欢

转载自blog.csdn.net/runewbie/article/details/102759050