mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比,于是写了个插件。 (2)

简介: mybatis 逆向工程使用姿势不对,把表清空了,心里慌的一比,于是写了个插件。 (2)

mybatis 插件开发


基于上面这三步,大家先看一下我们这插件怎么写,以及这个插件的效果。


先说明一下本文涉及到的源码 mybatis 版本是 3.4.0。


本文用拦截器的目的是判断 delete 语句中是否有 where 条件。所以,开发出来的插件长这样:


再来一个复制粘贴直接运行版本:


@Slf4j
@Intercepts({
        @Signature(type = Executor.class, method = "update",
                args = {MappedStatement.class, Object.class}),
})
public class CheckSQLInterceptor implements Interceptor {
    private static String SQL_WHERE = "where";
    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        //获取方法的第0个参数,也就是MappedStatement。@Signature注解中的args中的顺序
        MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
        //获取sql命令操作类型
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        final Object[] queryArgs = invocation.getArgs();
        final Object parameter = queryArgs[1];
        BoundSql boundSql = mappedStatement.getBoundSql(parameter);
        String sql = boundSql.getSql();
        if (SqlCommandType.DELETE.equals(sqlCommandType)) {
            //格式化sql
            sql = sql.replace("\n", "");
            if (!sql.toLowerCase().contains(SQL_WHERE)) {
                sql = sql.replace(" ", "");
                log.info("删除语句中没有where条件,sql为:{}", sql);
                throw new Exception("删除语句中没有where条件");
            }
        }
        return invocation.proceed();
    }
    @Override
    public Object plugin(Object o) {
        return Plugin.wrap(o, this);
    }
    @Override
    public void setProperties(Properties properties) {
    }
}


再把插件注册上(注册插件还有其他的方法,后面会讲到,这里只是展示Bean注入的方式):


我们先看看配上插件后的执行效果:


可以看到日志中输出了:


删除语句中没有where条件,sql为:delete from order_info_ext

并抛出了异常。


这样,我们的扩展表的数据就保住了。在测试阶段,测试同学就一定能扯出来问题,瞟一眼日志就明白了。


就算测试同学忘记测试了,在生产上也不会执行成功,抛出异常后还会有报警短信通知到相应的开发负责人,及时登上服务器去处理。


功能实现了,确实是非常的简单。


我们再说回代码,你说说看:当你拿到上面这段代码后,最迷惑的地方是哪里?


其中的逻辑是很简单的了。 没有什么特别的地方,我想大多数人拿到这段代码迷惑的地方在于这个地方吧:


这个 @Intercepts 里面的 @Signature 里面为什么要这样配置?

我们先看看 @Intercepts 注解:


里面是个数组,可以配置多个 Signature。所以,其实这样配置也是可以的:


关键的地方在于 @Signature 怎么配置:


这个问题,我们放到下一节去讨论。


mybatis插件的原理


上面一小节我们知道了对于开发插件而言,难点在于 @Signature 怎么配置。


其实这也不能叫难点,只能说你不知道能配置什么,比较茫然而已。这一小节就来回答这个问题。


要知道怎么配置就必须要了解mybatis 这四大对象:Executor、ParameterHandler 、ResultSetHandler 、StatementHandler 。


官网上说:


MyBatis 允许你在映射语句执行过程中的某一点进行拦截调用。默认情况下,MyBatis 允许使用插件来拦截的方法调用包括:


Executor (update, query, flushStatements, commit, rollback, getTransaction, close, isClosed)


ParameterHandler (getParameterObject, setParameters)


ResultSetHandler (handleResultSets, handleOutputParameters)


StatementHandler (prepare, parameterize, batch, update, query)


那官网上说的这四大对象分别是拿来干啥用的呢?


Executor:Mybatis 的执行器,用于进行增删改查的操作。


ParameterHandler :参数处理器,用于处理 SQL 语句中的参数对象。


ResultSetHandler:结果处理器,用于处理 SQL 语句的返回结果。


StatementHandler :数据库的处理对象,用于执行SQL语句


知道拦截的四大对象了,我们就可以先揭秘一下上面的这个注解配置的是啥了:


type 字段存放的是 class 对象,其取值范围就是上面说的四大对象。


method 字段存放的是 class 对象的具体方法。


args 存放的是具体方法的参数。


看到这几个参数你想到了什么?有没有条件反射式的想到反射?如果没有的话你再咂摸咂摸,看看能不能品出一点反射的味道。


本文用拦截器的目的是判断 delete 语句中是否有 where 条件,因此经过上面的分析,Executor 对象就能满足我们的需求。


所以在本文示例中 @Signature 的 type 字段就是 Executor.class。


那 method 字段我们放哪个方法呢?放 delete 吗?


这就得看看 Executor 对象的方法有哪些:


可以看到其中并没有 delete 方法,和 SQL 执行相关的,看起来只有 query和 update。

但是,我们可以大胆猜测一下呀:delete 也是一种 update。


接着去求证一下就行:


可以看到 delete 方法确实是调用了 update 方法。


所以在本文案例中 @Signature 的 method 字段放的是 update 方法。


已经知道具体的方法了,那 args 放的就是方法的入参,所以这段配置就是这样来的:


真的,我觉得这属于手摸手教学系列了。经过这个简单的案例,我希望大家能做到一通百通。


接下来带大家看看我们常用的分页插件 pageHelper 是怎么做的吧。


其实你用脚指头也能想到,分页插件肯定是拦截的查询方法,我们只是需要去验证一下就可以。


引入 pageHelper 后可以看到 Interceptor 的多了两个实现:


我们看一下 PageInterceptor 方法吧:


对吧,拦截了两个 query 方法,一个参数是 4 个,一个参数是 6 个:


同时,在 intercept 的实现里面有一部分是这样写的:


4 个参数和 6 个参数是做了单独处理的,至于为什么要这样处理,至于为什么要拦截两个 query 方法,说起来又是一个很长的故事了。


详细的可以看看这个链接: https://github.com/pagehelper/Mybatis-PageHelper/blob/master/wikis/zh/Interceptor.md


好了,还是那句话:如果要写出好的 mybatis 插件,必须知道 @Signature 怎么去配置。配置后能拦截哪些东西,你心里应该是有点数的。

目录
相关文章
|
5月前
|
Java 数据库连接 数据库
Spring boot 使用mybatis generator 自动生成代码插件
本文介绍了在Spring Boot项目中使用MyBatis Generator插件自动生成代码的详细步骤。首先创建一个新的Spring Boot项目,接着引入MyBatis Generator插件并配置`pom.xml`文件。然后删除默认的`application.properties`文件,创建`application.yml`进行相关配置,如设置Mapper路径和实体类包名。重点在于配置`generatorConfig.xml`文件,包括数据库驱动、连接信息、生成模型、映射文件及DAO的包名和位置。最后通过IDE配置运行插件生成代码,并在主类添加`@MapperScan`注解完成整合
938 1
Spring boot 使用mybatis generator 自动生成代码插件
|
6月前
|
SQL Java 数据安全/隐私保护
发现问题:Mybatis-plus的分页总数为0,分页功能失效,以及多租户插件的使用。
总的来说,使用 Mybatis-plus 确实可以极大地方便我们的开发,但也需要我们理解其工作原理,掌握如何合适地使用各种插件。分页插件和多租户插件是其中典型,它们的运用可以让我们的代码更为简洁、高效,理解和掌握好它们的用法对我们的开发过程有着极其重要的意义。
659 15
|
9月前
|
XML Java 数据库连接
十一、MyBatis的逆向工程
十一、MyBatis的逆向工程
228 6
十一、MyBatis的逆向工程
|
9月前
|
XML SQL Java
十二、MyBatis分页插件
十二、MyBatis分页插件
254 17
|
SQL Java 数据库连接
深入 MyBatis-Plus 插件:解锁高级数据库功能
Mybatis-Plus 提供了丰富的插件机制,这些插件可以帮助开发者更方便地扩展 Mybatis 的功能,提升开发效率、优化性能和实现一些常用的功能。
1356 26
深入 MyBatis-Plus 插件:解锁高级数据库功能
|
12月前
|
SQL Java 数据库连接
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
MyBatis-Plus是一个MyBatis的增强工具,在 MyBatis 的基础上只做增强不做改变,为简化开发、提高效率而生。本文讲解了最新版MP的使用教程,包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段等核心功能。
1822 5
【MyBatisPlus·最新教程】包含多个改造案例,常用注解、条件构造器、代码生成、静态工具、类型处理器、分页插件、自动填充字段
|
SQL 缓存 Java
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
本文详细介绍了MyBatis的各种常见用法MyBatis多级缓存、逆向工程、分页插件 包括获取参数值和结果的各种情况、自定义映射resultMap、动态SQL
【详细实用のMyBatis教程】获取参数值和结果的各种情况、自定义映射、动态SQL、多级缓存、逆向工程、分页插件
|
12月前
|
Java 数据库连接 数据库
spring和Mybatis的逆向工程
通过本文的介绍,我们了解了如何使用Spring和MyBatis进行逆向工程,包括环境配置、MyBatis Generator配置、Spring和MyBatis整合以及业务逻辑的编写。逆向工程极大地提高了开发效率,减少了重复劳动,保证了代码的一致性和可维护性。希望这篇文章能帮助你在项目中高效地使用Spring和MyBatis。
260 1
|
8月前
|
XML Java 数据库连接
微服务——SpringBoot使用归纳——Spring Boot集成MyBatis——基于注解的整合
本文介绍了Spring Boot集成MyBatis的两种方式:基于XML和注解的形式。重点讲解了注解方式,包括@Select、@Insert、@Update、@Delete等常用注解的使用方法,以及多参数时@Param注解的应用。同时,针对字段映射不一致的问题,提供了@Results和@ResultMap的解决方案。文章还提到实际项目中常结合XML与注解的优点,灵活使用两者以提高开发效率,并附带课程源码供下载学习。
667 0
|
10月前
|
前端开发 Java 数据库连接
Java后端开发-使用springboot进行Mybatis连接数据库步骤
本文介绍了使用Java和IDEA进行数据库操作的详细步骤,涵盖从数据库准备到测试类编写及运行的全过程。主要内容包括: 1. **数据库准备**:创建数据库和表。 2. **查询数据库**:验证数据库是否可用。 3. **IDEA代码配置**:构建实体类并配置数据库连接。 4. **测试类编写**:编写并运行测试类以确保一切正常。
441 2