MyBatis-Plus 拦截器

MyBatis-Plus 拦截器

MyBatis-Plus 是一个基于 MyBatis 的增强工具,旨在简化数据库操作的复杂性,提高开发效率。在 MyBatis-Plus 中,拦截器是一种强大的功能,允许你在 SQL 执行前后进行自定义的操作。本文将详细探讨 MyBatis-Plus 拦截器的工作原理、使用方法以及应用场景。

一、什么是 MyBatis-Plus 拦截器?

MyBatis-Plus 拦截器是一个实现了 MyBatis 拦截器接口的组件,可以在 MyBatis 的执行过程中拦截和处理 SQL 语句。它允许开发者在 SQL 执行前后插入自定义的逻辑,例如记录日志、修改 SQL 语句等。

二、MyBatis-Plus 拦截器的工作原理

MyBatis-Plus 拦截器的核心是 MyBatis 提供的 Interceptor 接口。开发者可以通过实现 Interceptor 接口来创建自定义的拦截器。MyBatis 在执行 SQL 语句时,会调用这些拦截器的相应方法,从而实现自定义的操作。

拦截器的工作流程如下:

  1. 注册拦截器:在 MyBatis 配置文件中或通过 Spring Boot 的配置文件中注册自定义拦截器。
  2. 拦截 SQL 执行:拦截器会在 SQL 执行的过程中被调用,你可以在这些拦截器中实现自定义逻辑。
  3. 执行后处理:拦截器可以在 SQL 执行后对结果进行处理,或者在 SQL 执行前对 SQL 进行修改。
1. MyBatis 拦截器机制概述

MyBatis 的拦截器机制允许开发者在 MyBatis 的执行流程中插入自定义逻辑。MyBatis 的拦截器可以拦截四个主要的组件:

  • Executor:负责执行 SQL 语句的组件。
  • StatementHandler:负责准备 SQL 语句并将其传递给数据库的组件。
  • ParameterHandler:负责将参数设置到 SQL 语句中的组件。
  • ResultSetHandler:负责处理查询结果集的组件。

拦截器通过实现 Interceptor 接口,并在 @Signature 注解中指定要拦截的方法,可以拦截这些组件的操作方法。

2. MyBatis 拦截器的生命周期
  1. 拦截器注册 :在 MyBatis 配置文件中或通过 SqlSessionFactory 配置时注册拦截器。
  2. 拦截器实例化 :MyBatis 会创建拦截器实例,并通过 plugin 方法对目标对象进行包装。
  3. 方法拦截 :在目标方法执行前后,拦截器可以插入自定义逻辑。在执行 intercept 方法时,可以通过 Invocation 对象访问目标方法的信息。
  4. 目标方法执行 :拦截器在执行自定义逻辑后,通常会调用目标方法的 proceed 方法,确保原始功能得以保留。
  5. 拦截器链:多个拦截器可以链式调用,依次拦截目标方法。

三、如何使用 MyBatis-Plus 拦截器

1. 创建自定义拦截器

首先,你需要实现 Interceptor 接口。以下是一个简单的自定义拦截器的示例:

java 复制代码
import org.apache.ibatis.executor.statement.StatementHandler;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import java.sql.Connection;
import java.sql.Statement;
import java.util.Properties;

@Intercepts({
    @Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})
})
public class MyCustomInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        // 获取 StatementHandler 对象
        StatementHandler statementHandler = (StatementHandler) invocation.getTarget();
        
        // 打印 SQL 语句
        System.out.println("Intercepted SQL: " + statementHandler.getBoundSql().getSql());
        
        // 执行原始的处理过程
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object target) {
        return Interceptor.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
        // 可以通过 properties 设置一些属性
    }
}

2. 注册拦截器

自定义拦截器的注册可以通过 MyBatis 配置文件或 Spring Boot 配置类进行

java 复制代码
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.autoconfigure.MybatisPlusProperties;
import com.baomidou.mybatisplus.autoconfigure.SpringBootVFS;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.toolkit.GlobalConfigUtils;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.InnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.google.common.collect.Lists;
import com.aa.bb.cc.dd.test.handler.QueryStatisticsInterceptor;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.SqlSessionTemplate;
import org.mybatis.spring.mapper.ClassPathMapperScanner;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.env.Environment;
import org.springframework.core.env.PropertySource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.util.StringUtils;
import javax.sql.DataSource;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import java.util.Properties;

@Slf4j
@Configuration
public class OPPConfiguration implements EnvironmentAware,BeanFactoryAware{

	@Autowired(required = false)
	private DataSource dataSource;

	private BeanFactory beanFactory;

	@Bean("sqlSessionFactory")
	@Primary
	public SqlSessionFactory sqlSessionFactory() throws Exception {

		MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
		sqlSessionFactoryBean.setDataSource(this.dataSource);
		sqlSessionFactoryBean.setMapperLocations(new   PathMatchingResourcePatternResolver().getResources("classpath*:com/aa/bb/cc/**/mapper/**/**.xml"));
		sqlSessionFactoryBean.setVfs(SpringBootVFS.class);
		MybatisPlusInterceptor interceptor=new MybatisPlusInterceptor();

		List<InnerInterceptor> interceptors = Lists.newArrayList(interceptor.getInterceptors());
		interceptors.clear();
		PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
		// 分页插件
		interceptors.add(paginationInnerInterceptor);
		// 乐观锁插件
		interceptors.add(new OptimisticLockerInnerInterceptor());

		interceptor.setInterceptors(interceptors);
		GlobalConfig globalConfig = GlobalConfigUtils.defaults();
		GlobalConfig.DbConfig dbConfig = new GlobalConfig.DbConfig();
		globalConfig.setDbConfig(dbConfig);
		globalConfig.setMetaObjectHandler(new OpaMetaObjectHandler());

		globalConfig.setSqlInjector(new EasySqlInjector());
		sqlSessionFactoryBean.setGlobalConfig(globalConfig);
		sqlSessionFactoryBean.getObject().getConfiguration().addInterceptor(interceptor);
        //注册自定义拦截器
		sqlSessionFactoryBean.getObject().getConfiguration().addInterceptor(new QueryStatisticsInterceptor());

		SqlSessionFactory sqlSessionFactory=sqlSessionFactoryBean.getObject();
		SqlSessionTemplate sqlSessionTemplate = new SqlSessionTemplate(sqlSessionFactory);
		ClassPathMapperScanner scanner = new ClassPathMapperScanner((BeanDefinitionRegistry) beanFactory);
		scanner.setSqlSessionTemplate(sqlSessionTemplate);
		scanner.registerFilters();
		scanner.scan("com.aa.bb.cc.cc.test.dao","com.aa.bb.cc.dao");
		return sqlSessionFactoryBean.getObject();
	}

3. 使用拦截器

创建了自定义拦截器并注册后,当 SQL 执行时,MyCustomInterceptor 将拦截并打印 SQL 语句。你可以根据需要在 intercept 方法中实现更复杂的逻辑,如修改 SQL、记录日志等。

四、常见拦截器应用场景

  1. SQL 日志记录:记录所有执行的 SQL 语句及其执行时间,以便进行性能监控和调试。
  2. 动态 SQL 修改:在执行前动态修改 SQL 语句,如添加调试信息或修改查询条件。
  3. 性能监控:记录 SQL 执行时间,分析性能瓶颈。
  4. 权限控制:根据用户权限动态修改 SQL 查询。

五、常见 MyBatis Plus 拦截器

  • 分页拦截器

分页拦截器 PaginationInterceptor 是 MyBatis Plus 提供的一个重要拦截器,用于处理分页查询。它会自动识别分页参数,并在 SQL 中添加相应的分页条件。

  • 乐观锁拦截器

乐观锁拦截器 OptimisticLockerInterceptor 用于处理乐观锁机制,确保在并发更新时数据的一致性。它会在 SQL 中添加 version 字段,以支持乐观锁的检查和更新。

  • 性能分析拦截器

性能分析拦截器 PerformanceInterceptor 用于打印 SQL 执行的性能分析信息,包括 SQL 执行时间等。它帮助开发者识别性能瓶颈和优化 SQL 查询。

六、注意事项

  1. 性能影响:拦截器的逻辑会增加额外的开销,尤其是在复杂的拦截器中,因此要注意性能影响。
  2. 调试与测试:在使用拦截器时,要确保对其进行充分的测试,以避免引入潜在的 bug。
  3. 兼容性:不同版本的 MyBatis 和 MyBatis-Plus 可能对拦截器的支持有所不同,确保使用兼容的版本。

结语

MyBatis-Plus 拦截器为开发者提供了强大的自定义能力,可以在 SQL 执行过程中插入各种业务逻辑。通过合理使用拦截器,可以大大提升开发效率和系统性能。希望本文对你了解和使用 MyBatis-Plus 拦截器有所帮助。

相关推荐
李慕婉学姐5 小时前
【开题答辩过程】以《基于JAVA的校园即时配送系统的设计与实现》为例,不知道这个选题怎么做的,不知道这个选题怎么开题答辩的可以进来看看
java·开发语言·数据库
奋进的芋圆6 小时前
Java 延时任务实现方案详解(适用于 Spring Boot 3)
java·spring boot·redis·rabbitmq
sxlishaobin7 小时前
设计模式之桥接模式
java·设计模式·桥接模式
model20057 小时前
alibaba linux3 系统盘网站迁移数据盘
java·服务器·前端
荒诞硬汉7 小时前
JavaBean相关补充
java·开发语言
提笔忘字的帝国7 小时前
【教程】macOS 如何完全卸载 Java 开发环境
java·开发语言·macos
2501_941882487 小时前
从灰度发布到流量切分的互联网工程语法控制与多语言实现实践思路随笔分享
java·开发语言
華勳全栈8 小时前
两天开发完成智能体平台
java·spring·go
alonewolf_998 小时前
Spring MVC重点功能底层源码深度解析
java·spring·mvc
沛沛老爹8 小时前
Java泛型擦除:原理、实践与应对策略
java·开发语言·人工智能·企业开发·发展趋势·技术原理