Mybatis的拦截器学习

简介: 可以创建一个拦截器来拦截 MyBatis 在执行 SQL 语句前后的一些操作,例如修改 SQL 语句、记录 SQL 执行时间等。

当你在使用 MyBatis 框架时,你可以创建一个拦截器来拦截 MyBatis 在执行 SQL 语句前后的一些操作,例如修改 SQL 语句、记录 SQL 执行时间等。在 MyBatis 中,拦截器使用注解 @Intercepts 来标记,而 @Signature 注解则用来标记要拦截的方法。

@Signature 注解中有三个属性:

  1. type:指定要拦截的接口或类,例如 Executor.class,StatementHandler.class 等;
  2. method:指定要拦截的方法名,例如 update、query 等;
  3. args:指定要拦截的方法的参数类型数组,例如 {MappedStatement.class, Object.class},表示要拦截的方法有两个参数,第一个参数的类型是 MappedStatement,第二个参数的类型是 Object。

当你使用了 @Signature 注解后,你就可以将拦截器应用到 MyBatis 的 SQL 执行过程中。在这个过程中,如果执行的方法名、参数类型和数量等与 @Signature 中定义的一致,那么拦截器就会被调用。

下面是一个使用 @Intercepts@Signature 注解的例子:

@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 {
    // 在执行 SQL 语句之前,可以修改 SQL 语句或者记录 SQL 执行时间等操作
    Object result = invocation.proceed();
    // 在执行 SQL 语句之后,可以对返回结果进行处理,例如加密数据等操作
    return result;
  }
}

在这个例子中,我们创建了一个拦截器 MyInterceptor,并使用 @Intercepts 注解标记。我们将要拦截的接口类型指定为 Executor.class,要拦截的方法名为 update,参数类型数组为 {MappedStatement.class, Object.class}。

这个拦截器会在执行 Executor 接口中的 update 方法之前和之后被调用,并可以在方法执行前后做一些额外的操作。

除了这个例子,MyBatis 的官方文档中也提供了其他的 @Signature 注解的使用例子,你可以查看这个链接:https://mybatis.org/mybatis-3/zh/configuration.html#plugins

在 MyBatis 中,MappedStatement 类型的参数代表了执行的 SQL 语句,它包含了 SQL 语句的 ID、参数类型、返回类型、SQL 语句字符串等信息。MappedStatement 参数可以通过 Invocation 对象的 getArgs() 方法获取到。

在上面的例子中,我们使用 @Signature 注解指定了拦截器要拦截的方法是 Executor.update(MappedStatement ms, Object parameter)。其中,MappedStatement 类型的参数就是用来传递 SQL 语句信息的。

至于 Object 类型的参数,则是传递给 SQL 语句的参数对象,它可以是任何类型的 Java 对象。在执行 SQL 语句时,MyBatis 会根据 MappedStatement 中定义的参数类型来将 Object 类型的参数转换为对应的 SQL 参数。

总之,MappedStatement 类型的参数和 Object 类型的参数在执行 SQL 语句时都是必须的,它们分别代表了 SQL 语句信息和 SQL 参数。而在拦截器中,我们可以通过 Invocation 对象获取到这两个参数,并对它们进行处理。

MappedStatement 对象通常是 MyBatis 内部自动生成的,包含了 SQL 语句的 ID、参数类型、返回类型、SQL 语句字符串等信息。这个对象会在执行 SQL 语句时自动传入,我们不需要手动传入。

下面是 Executor 接口中 update 方法的源码:

javaCopy code
int update(MappedStatement ms, Object parameter) throws SQLException;

可以看到,在执行 update 方法时,需要传入 MappedStatementObject 类型的参数。这些参数是由 MyBatis 内部调用时传入的。

在 MyBatis 的执行过程中,MappedStatement 对象是在 Configuration 类的 buildAllMappedStatements() 方法中生成的,而参数对象 parameter 则是在执行 SQL 语句时通过 BoundSql 对象与 MappedStatement 相关联生成的。

Mybatis源码学习推荐

  1. MyBatis 官方文档:官方文档中详细介绍了 MyBatis 的各个模块和功能,包括使用、配置、插件等方面,是入门和进阶的必备参考资料。
  2. MyBatis 源代码:MyBatis 是开源项目,源代码可以在官方 GitHub 上找到,可以通过阅读源代码深入了解 MyBatis 的实现原理。
  3. MyBatis 揭秘:这是一本 MyBatis 实现原理的书籍,作者是 MyBatis 的核心开发者之一,详细讲解了 MyBatis 的设计和实现,包括 SQL 解析、映射、缓存、事务等方面。
  4. 《深入浅出MyBatis技术原理与实战》:这是一本非常适合入门的 MyBatis 书籍,讲解了 MyBatis 的基本使用和实现原理,并提供了实例演示,非常适合初学者入门。

@Signature 注解中的 args 数组可以指定被拦截方法的参数类型,可以放任意类型,例如:int.classString.class 等。拦截器会根据指定的参数类型匹配方法的参数类型,只有匹配成功才会拦截该方法。

在 MyBatis 中,@Signature 注解中常用的参数类型除了 MappedStatementObject 之外,还有:

  1. ResultHandler.class:结果处理器,用于处理查询结果,通常在查询大量数据时使用。
  2. RowBounds.class:行分页限制器,用于控制查询的结果数量和偏移量,通常用于分页查询。
  3. CacheKey.classCacheValue.class:用于缓存数据的键和值类型。

除此之外,还可以根据需要自定义参数类型,例如:

@Intercepts({
    @Signature(type = Executor.class, method = "query", args = {
        MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class
    })
})

这里指定了被拦截的方法为 query,参数类型包括 MappedStatement.classObject.classRowBounds.classResultHandler.class,即查询方法的参数类型。

在 MyBatis 中,Interceptor 接口的 intercept 方法中的 Invocation 参数表示被拦截的方法调用,其中的 getArgs 方法返回了被拦截方法的参数列表,是一个数组。

因为在 @Signature 注解中我们指定了被拦截方法的参数类型为 {MappedStatement.class, Object.class},所以 getArgs()[0] 表示的是被拦截方法的第一个参数 MappedStatementgetArgs()[1] 表示的是被拦截方法的第二个参数 Object

所以,invocation.getArgs()[1] 表示的是被拦截方法的第二个参数,即传入到 SQL 语句中的实际参数。在拦截器中,我们可以通过修改这个参数来改变执行 SQL 语句的行为,或者在执行 SQL 语句前后执行一些其他逻辑。

目录
相关文章
|
1月前
|
Java 关系型数据库 MySQL
springboot学习五:springboot整合Mybatis 连接 mysql数据库
这篇文章是关于如何使用Spring Boot整合MyBatis来连接MySQL数据库,并进行基本的增删改查操作的教程。
75 0
springboot学习五:springboot整合Mybatis 连接 mysql数据库
|
2月前
|
SQL Java 数据库连接
解决mybatis-plus 拦截器不生效--分页插件不生效
本文介绍了在使用 Mybatis-Plus 进行分页查询时遇到的问题及解决方法。依赖包包括 `mybatis-plus-boot-starter`、`mybatis-plus-extension` 等,并给出了正确的分页配置和代码示例。当分页功能失效时,需将 Mybatis-Plus 版本改为 3.5.5 并正确配置拦截器。
612 6
解决mybatis-plus 拦截器不生效--分页插件不生效
|
2月前
|
Java 关系型数据库 数据库连接
mybatis-plus学习
MyBatis-Plus ,MyBatis 最佳搭档,只做增强不做改变,为简化开发、提高效率而生。
46 5
|
3月前
|
安全 Java 数据库连接
后端框架的学习----mybatis框架(3、配置解析)
这篇文章详细介绍了MyBatis框架的核心配置文件解析,包括环境配置、属性配置、类型别名设置、映射器注册以及SqlSessionFactory和SqlSession的生命周期和作用域管理。
后端框架的学习----mybatis框架(3、配置解析)
|
3月前
|
Java 数据库连接 mybatis
后端框架的学习----mybatis框架(9、多对一处理和一对多处理)
这篇文章介绍了在MyBatis框架中如何处理多对一和一对多的关联查询,通过定义`<resultMap>`和使用`<association>`与`<collection>`元素来实现对象间的关联映射。
|
3月前
|
Java 数据库连接 测试技术
后端框架的学习----mybatis框架(8、lombok)
这篇文章介绍了如何在MyBatis框架中使用lombok库来简化Java实体类的编写,包括在IDEA中安装Lombok插件、在项目中导入lombok依赖以及在实体类上使用Lombok提供的注解。
|
3月前
|
Java 数据库连接 数据库
后端框架的学习----mybatis框架(6、日志)
这篇文章介绍了如何在MyBatis框架中使用日志功能,包括配置MyBatis的日志实现、使用log4j作为日志工具,以及如何通过配置文件控制日志级别和输出格式。
|
3月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(5、分页)
这篇文章介绍了如何在MyBatis框架中实现分页功能,包括使用SQL的`limit`语句进行分页和利用MyBatis的`RowBounds`对象进行分页的方法。
|
3月前
|
SQL Java 数据库连接
后端框架的学习----mybatis框架(7、使用注解开发)
这篇文章讲述了如何使用MyBatis框架的注解方式进行开发,包括在接口上使用注解定义SQL语句,并通过动态代理实现对数据库的增删改查操作,同时强调了接口需要在核心配置文件中注册绑定。
|
5月前
|
SQL 人工智能 Java
mybatis-plus配置sql拦截器实现完整sql打印
_shigen_ 博主分享了如何在MyBatis-Plus中打印完整SQL,包括更新和查询操作。默认日志打印的SQL用?代替参数,但通过自定义`SqlInterceptor`可以显示详细信息。代码示例展示了拦截器如何替换?以显示实际参数,并计算执行时间。配置中添加拦截器以启用此功能。文章提到了分页查询时的限制,以及对AI在编程辅助方面的思考。
676 5
mybatis-plus配置sql拦截器实现完整sql打印