上一节我们学习了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
:
- 在 Mapper 接口中定义相关的 CRUD 方法
- 扩展 AbstractMethod 的 injectMappedStatement 方法,实现 Mapper 接口中方法要注入的 SQL
- 扩展 DefaultSqlInjector ,重写 getMethodList 方法,添加自定义方法
- 修改
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
路径下新建一个和EmployeeMapper
中deleteAll()
方法同名的类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);
}
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">-->
<!-- <!– 禁止全表删除–>-->
<!-- <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的代码结构如下所示:
至此,基于 mybatis-plus
的自定义全局操作和全局sql注入
演示就完成了,下面我们就可以进入到下一节公共字段自动填充
的学习了。
源代码
相关示例完整代码:mybatis-plus-in-action