目录
1 、ActiveRecord
1、开启AR
2 、插件
1、mybatis的插件机制
2、执行分析插件
3、性能分析插件
4、乐观锁插件
3、Sql 注入器
4、自动填充功能
5、逻辑删除
6、通用枚举
7、MybatisX 快速开发插件
1 、ActiveRecord
ActiveRecord(简称AR)一直广受动态语言( PHP 、 Ruby 等)的喜爱,而 Java 作为准静态语言,对于ActiveRecord 往往只能感叹其优雅,所以我们也在 AR 道路上进行了一定的探索,喜欢大家能够喜欢。
![](https://img-blog.csdnimg.cn/20210718085146941.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
1、开启AR
在MP中,开启AR非常简单,只需要将实体对象继承Model即可。
![](https://img-blog.csdnimg.cn/20210718085814185.png)
![](https://img-blog.csdnimg.cn/20210718085827809.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
这里不用注入UserMapper,但是不能没有UserMapper类,底层代码会用到它
![](https://img-blog.csdnimg.cn/20210718093653886.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210718093737404.png)
![](https://img-blog.csdnimg.cn/20210718093934860.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
2 、插件
1、mybatis的插件机制
MyBatis 允许你在已映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法
调用包括:
1. Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)
2. ParameterHandler (getParameterObject, setParameters)
3. ResultSetHandler (handleResultSets, handleOutputParameters)
4. StatementHandler (prepare, parameterize, batch, update, query)
我们看到了可以拦截Executor接口的部分方法,比如update,query,commit,rollback等方法,还有其他接口的一些方法等。
总体概括为:
1. 拦截执行器的方法
2. 拦截参数的处理
3. 拦截结果集的处理
4. 拦截Sql语法构建的处理
package com.mybatis.plugins;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.plugin.*;
import java.util.Properties;
@Intercepts({@Signature(
type= Executor.class,
method = "update",//指定拦截方法名
args = {MappedStatement.class,Object.class})})
public class MyInterceptor implements Interceptor {
@Override
public Object intercept(Invocation invocation) throws Throwable {
//拦截方法,具体业务逻辑编写的位置
return invocation.proceed();
}
@Override
public Object plugin(Object target) {
//创建target对象的代理对象,目的是将当前拦截器加入到该对象中
return Plugin.wrap(target, this);
}
@Override
public void setProperties(Properties properties) {
//属性设置
}
}
![](https://img-blog.csdnimg.cn/20210718125508171.png)
或者
<configuration>
<plugins>
<plugin interceptor="cn.itcast.mp.plugins.MyInterceptor"></plugin>
</plugins>
</configuration>
2、执行分析插件
在MP中提供了对SQL执行的分析的插件,可用作阻断全表更新、删除的操作,注意:该插件仅适用于开发环境,不适用于生产环境。
SpringBoot配置:
@Bean
public SqlExplainInterceptor sqlExplainInterceptor(){
SqlExplainInterceptor sqlExplainInterceptor = new SqlExplainInterceptor();
List<ISqlParser> sqlParserList = new ArrayList<>();
// 攻击 SQL 阻断解析器、加入解析链
sqlParserList.add(new BlockAttackSqlParser());
sqlExplainInterceptor.setSqlParserList(sqlParserList);
return sqlExplainInterceptor;
}
![](https://img-blog.csdnimg.cn/20210718133117949.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210718133142940.png)
3、性能分析插件
性能分析拦截器,用于输出每条 SQL 语句及其执行时间,可以设置最大执行时间,超过时间会抛出异常。
该插件只用于开发环境,不建议生产环境使用。
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor">
<!--最大的执行时间,毫秒-->
<property name="maxTime" value="100"/>
<!--对输出的SQL进行格式化,默认false-->
<property name="format" value="true"/>
</plugin>
![](https://img-blog.csdnimg.cn/20210718155906412.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
4、乐观锁插件
当要更新一条记录的时候,希望这条记录没有被别人更新
乐观锁实现方式:
- 取出记录时,获取当前 version
- 更新时,带上这个 version
- 执行更新时, set version = newVersion where version = oldVersion
- 如果 version不对,就更新失败
spring xml:
< bean class="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"/>
spring boot:
<plugin interceptor="com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor"></plugin>
第一步,为数据库表添加version字段,并且设置初始值为1:
第二步,为User实体对象添加version字段,并且添加@Version注解:
![](https://img-blog.csdnimg.cn/2021071816103052.png)
![](https://img-blog.csdnimg.cn/20210718161956393.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210718162009329.png)
执行完后,version值自动+1
![](https://img-blog.csdnimg.cn/20210718162347148.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
注意事项:
- 支持的数据类型只有 :int,Integer,long,Long,Date,Timestamp,LocalDateTime
- 整数类型下 newVersion = oldVersion + 1
- newVersion 会回写到 entity 中
- 仅支持 updateById(id) 与 update(entity, wrapper) 方法
- 在 update(entity, wrapper) 方法下, wrapper 不能复用!!!
3、Sql 注入器
我们已经知道,在MP中,通过AbstractSqlInjector将BaseMapper中的方法注入到了Mybatis容器,这样这些方法才可以正常执行。
那么,如果我们需要扩充BaseMapper中的方法,又该如何实现呢?
![](https://img-blog.csdnimg.cn/20210719085923352.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/20210719085945227.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
FindAll
package com.mybatis.injector;
import com.baomidou.mybatisplus.core.injector.AbstractMethod;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
public class FindAll extends AbstractMethod {
@Override
public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
String sql = "select * from "+tableInfo.getTableName();
SqlSource sqlSource = languageDriver.createSqlSource(configuration,sql,modelClass);
return this.addSelectMappedStatement(mapperClass,"findAll",sqlSource,modelClass,tableInfo);
}
}
![](https://img-blog.csdnimg.cn/20210719091600402.png)
![](https://img-blog.csdnimg.cn/20210719091621613.png)
![](https://img-blog.csdnimg.cn/2021071909163698.png)
问题:BaseMapper中的方法会失效
![](https://img-blog.csdnimg.cn/20210719093109642.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
4、自动填充功能
有些时候我们可能会有这样的需求,插入或者更新数据时,希望有些字段可以自动填充数据,比如密码、version等。在MP中提供了这样的功能,可以实现自动填充。
![](https://img-blog.csdnimg.cn/20210719145603602.png)
package com.mybatis.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;
@Component
public class MyHandler implements MetaObjectHandler {
//插入数据时进行填充
@Override
public void insertFill(MetaObject metaObject) {
//先获取password的值,再进行判断,空就填充,不为空,就不做处理
Object password = getFieldValByName("password", metaObject);
if(password == null){
setFieldValByName("password","5555",metaObject);
}
}
@Override
public void updateFill(MetaObject metaObject) {
}
}
![](https://img-blog.csdnimg.cn/20210719145908789.png)
![](https://img-blog.csdnimg.cn/20210719145851658.png)
5、逻辑删除
开发系统时,有时候在实现功能时,删除操作需要实现逻辑删除,所谓逻辑删除就是将数据标记为删除,而并非真正的物理删除(非DELETE操作),查询时需要携带状态条件,确保被标记的数据不被查询到。这样做的目的就是避免数据被真正的删除。
先给表添加deleted字段
![](https://img-blog.csdnimg.cn/20210719151321252.png)
#删除为1
mybatis-plus.global-config.db-config.logic-delete-value=1
#未删除为0
mybatis-plus.global-config.db-config.logic-not-delete-value=0
![](https://img-blog.csdnimg.cn/20210719151350751.png)
底层执行的是update,不是delete
![](https://img-blog.csdnimg.cn/20210719151417294.png)
查询时
![](https://img-blog.csdnimg.cn/20210719151721674.png)
![](https://img-blog.csdnimg.cn/2021071915171150.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
6、通用枚举
解决了繁琐的配置,让 mybatis 优雅的使用枚举属性!
先给表添加sex字段
package com.mybatis.enums;
import com.baomidou.mybatisplus.core.enums.IEnum;
public enum SexEnum implements IEnum<Integer> {
MAN(1,"男"),
WOMAN(2,"女");
private int value;
private String desc;
SexEnum(int value, String desc){
this.value = value;
this.desc = desc;
}
@Override
public Integer getValue() {
return this.value;
}
@Override
public String toString() {
return this.desc;
}
}
![](https://img-blog.csdnimg.cn/20210719153201350.png)
# 枚举包扫描
mybatis-plus.type-enums-package=com.mybatis.enums
![](https://img-blog.csdnimg.cn/20210719153446902.png)
![](https://img-blog.csdnimg.cn/20210719153521242.png)
查询
![](https://img-blog.csdnimg.cn/20210719153658964.png)
7、MybatisX 快速开发插件
MybatisX 是一款基于 IDEA 的快速开发插件,为效率而生。
安装方法:打开 IDEA,进入 File -> Settings -> Plugins -> Browse Repositories,输入 mybatisx 搜索并安装。
功能:
- Java 与 XML 调回跳转
- Mapper 方法自动生成 XML
![](https://img-blog.csdnimg.cn/20210719163731571.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl81NjY5NzExNA==,size_16,color_FFFFFF,t_70)
![](https://img-blog.csdnimg.cn/2021071916412427.png)
![](https://img-blog.csdnimg.cn/20210719164309709.png)
![](https://img-blog.csdnimg.cn/20210719164325125.png)