mybatis @Intercepts的用法

Mybatis 动态修改 SQL 的两种方式 在Spring AOP中,你可以使用切面(Aspect)来拦截MyBatis执行期间的方法调用,包括修改BoundSql对象中的SQL语句。 阅读详情

1.拦截器类

package com.testmybatis.interceptor;

import java.util.Properties;

import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlSource;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Plugin;
import org.apache.ibatis.session.ResultHandler;
import org.apache.ibatis.session.RowBounds;
import org.apache.log4j.Logger;

@Intercepts({ @org.apache.ibatis.plugin.Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }) })
public class SqlInterceptor implements Interceptor {
	
	private Logger log=Logger.getLogger(getClass());

	public Object intercept(Invocation invocation) throws Throwable {
		// TODO Auto-generated method stub

		log.info("Interceptor......");

		// 获取原始sql语句
		MappedStatement mappedStatement = (MappedStatement) invocation.getArgs()[0];
		Object parameter = invocation.getArgs()[1];
		BoundSql boundSql = mappedStatement.getBoundSql(parameter);
		String oldsql = boundSql.getSql();
		log.info("old:"+oldsql);

		// 改变sql语句
		BoundSql newBoundSql = new BoundSql(mappedStatement.getConfiguration(), oldsql + " where id=1",
				boundSql.getParameterMappings(), boundSql.getParameterObject());
		MappedStatement newMs = copyFromMappedStatement(mappedStatement, new BoundSqlSqlSource(newBoundSql));
		invocation.getArgs()[0] = newMs;

		// 继续执行
		Object result = invocation.proceed();
		return result;
	}

	public Object plugin(Object target) {
		// TODO Auto-generated method stub
		return Plugin.wrap(target, this);
	}

	public void setProperties(Properties properties) {
		// TODO Auto-generated method stub

	}

	// 复制原始MappedStatement
	private MappedStatement copyFromMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
		MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource,
				ms.getSqlCommandType());
		builder.resource(ms.getResource());
		builder.fetchSize(ms.getFetchSize());
		builder.statementType(ms.getStatementType());
		builder.keyGenerator(ms.getKeyGenerator());
		if (ms.getKeyProperties() != null) {
			for (String keyProperty : ms.getKeyProperties()) {
				builder.keyProperty(keyProperty);
			}
		}
		builder.timeout(ms.getTimeout());
		builder.parameterMap(ms.getParameterMap());
		builder.resultMaps(ms.getResultMaps());
		builder.cache(ms.getCache());
		builder.useCache(ms.isUseCache());
		return builder.build();
	}

	public static class BoundSqlSqlSource implements SqlSource {
		BoundSql boundSql;

		public BoundSqlSqlSource(BoundSql boundSql) {
			this.boundSql = boundSql;
		}

		public BoundSql getBoundSql(Object parameterObject) {
			return boundSql;
		}
	}

}

2.拦截器配置

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
  PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>

	<plugins>
		<plugin interceptor="com.testmybatis.interceptor.SqlInterceptor" />
	</plugins>

	<environments default="development">
		<environment id="development">
			<transactionManager type="JDBC" />
			<dataSource type="POOLED">
				<property name="driver" value="com.mysql.cj.jdbc.Driver" />
				<property name="url"
					value="jdbc:mysql://127.0.0.1:3306/test?serverTimezone=UTC&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;useSSL=true" />
				<property name="username" value="root" />
				<property name="password" value="123456" />
			</dataSource>
		</environment>
	</environments>
	
	<mappers>
		<mapper resource="com/testmybatis/dao/TestMapper.xml" />
	</mappers>
	
</configuration>

3.测试接口及配置

package com.testmybatis.model;

import java.io.Serializable;

public class Test implements Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private int id;
	private String name;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	
	public String toString(){
		return "id:"+id+" name:"+name;
	}

}
package com.testmybatis.dao;

import java.util.List;

import org.apache.ibatis.annotations.Select;

import com.testmybatis.model.Test;


public interface TestMapper {
	public List<Test> test();
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.testmybatis.dao.TestMapper">

	<select id="test" resultType="com.testmybatis.model.Test">
		select * from test
	</select>

</mapper>

4.测试

	try {
			String resource = "com/testmybatis/mybatis-config.xml";
			InputStream inputStream = Resources.getResourceAsStream(resource);
			SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
			SqlSession session = sqlSessionFactory.openSession();
			try {
				TestMapper mapper=session.getMapper(TestMapper.class);
				List<Test> tests=mapper.test();
				session.commit();
				log.info(JSON.toJSONString(tests));
				
			} finally {
				session.close();
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

5.结果

配置了拦截器的情况下

2018-08-07 14:14:18 DEBUG [com.testmybatis.dao.TestMapper.test] ==>  Preparing: select * from test where id=1 
2018-08-07 14:14:18 DEBUG [com.testmybatis.dao.TestMapper.test] ==> Parameters: 
2018-08-07 14:14:18 DEBUG [com.testmybatis.dao.TestMapper.test] <==      Total: 1
2018-08-07 14:14:18 INFO [com.testmybatis.testlanjie] [{"id":1,"name":"adb"}]

没配置拦截器的情况下

2018-08-07 14:15:48 DEBUG [com.testmybatis.dao.TestMapper.test] ==>  Preparing: select * from test 
2018-08-07 14:15:48 DEBUG [com.testmybatis.dao.TestMapper.test] ==> Parameters: 
2018-08-07 14:15:48 DEBUG [com.testmybatis.dao.TestMapper.test] <==      Total: 8
2018-08-07 14:15:48 INFO [com.testmybatis.testlanjie] [{"id":1,"name":"adb"},{"id":2,"name":"dafdsa"},{"id":3,"name":"dafa"},{"id":4,"name":"fffff"},{"id":16,"name":"test"},{"id":17,"name":"test"},{"id":18,"name":"test"},{"id":19,"name":"zhenshide"}]

 

使用mybatis的@Interceptor实现拦截sql 拦截器是一种基于 AOP(面向切面编程)的技术,它可以在目标对象的方法执行前后插入自定义的逻辑。 阅读详情

相关推荐

SpringBoot整合MybatisSQL过滤@Intercepts的实现

主要介绍了SpringBoot整合MybatisSQL过滤@Intercepts的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

Mybatis拦截器

一 Mybatis拦截器介绍        Mybatis拦截器设计的初衷就是为了供用户在某些时候可以实现自己的逻辑而不必去动Mybatis固有的逻辑。通过Mybatis拦截器我们可以拦截某些方法的调用,我们可以选择在这些被拦截的方法执行前后加上某些逻辑,也可以在执行这些被拦截的方法时执行自己的逻辑而不再执行被拦截的方法。所以Mybatis拦截器的使用范围是...

旧路 6万+

primetime如何做voltage scaling

存在这样的情况,标准单元库只有ssgnp0p72vm40c和ssgnp0p9vm40c的libs,但是我们希望它工作在ssgnp0p76vm40c,这样的话就需要用ssgnp0p72vm40c和ssgnp0p9vm40c的libs来scaling出ssgnp0p76vm40c的lib。

qq_34326957的博客 1684

mybatis:拦截器Interceptor:

定义特定注解,在切入时需要检查字段中是否包含注解来是否加解密。Intercepts注解需要一个Signature(拦截点)参数数组。说明: @Intercepts:标识该类是一个拦截器;@Signature:指明自定义拦截器需要拦截哪一个类型,哪一个方法;Mybatis 插件的使用就是通过实现 Mybatis 中的 Interceptor 接口。这个方法的作用是就是让mybatis判断,是否要进行拦截,然后做出决定是否生成一个代理。3.ParameterHandler:拦截参数的处理。

QJY1437758743的博客 3875

反激变压器反射电压详解

我以前做过隔离式的POE模块,其电路实际就是个反激式开关电源。只不过其输入电压范围比较低,为44V-57V。 电路如下图,就是个flyback。 可以看到,电路中有个钳位电路,用来抑制电压尖峰,就在初级线圈那里。 问题 抑制尖峰通常有2种电路,一种叫RCD钳位,另外一种是用TVS管+二极管钳位。 这两种实际中都有用,今天我不想讨论它们的区别,只想说明一个问题: 为什么不能只用一个二极管搞定?像继电器电路那样?不也能抑制尖峰吗? 答案自然是不行的...

weixin_42005993的博客 2万+

MySQL 分库分表及其平滑扩容方案

MyCAT不仅仅可以用作读写分离,以及分表分库、容灾管理,而且可以用于多租户应用开发、云平台基础设施,让你的架构具备很强的适应性和灵活性。分表对于一张多行(记录)多列(字段)的二维数据表,又分两种情形(1)垂直分表竖向切分,不同分表存储不同的字段,可以把不常用或者大容量、或者不同业务的字段拆分出去;扩容前每个节点的数据,有一半要迁移至一个新增节点中,对应关系比较简单。此时,四个节点的数据都已完整,只是有冗余(多存了和自己配对的节点的那部分数据),择机清除即可(过后随时进行,不影响业务)。...

m0_71777195的博客 1929

MyBatis @Intercepts 实现打印 SQL 语句

文章目录1. @Intercepts 简介2. 使用 @Intercepts 实现打印 SQL 语句 1. @Intercepts 简介 2. 使用 @Intercepts 实现打印 SQL 语句

谈谈1974 8787

华为铁三角(AR、SR、FR)的考核指标设计

以和为核心,通过和实现协同。考核维度分为和,并随市场阶段动态调整权重。

从技术实践立足,从项目管理方法论延伸思考 2769

Mybatis拦截器注解@Intercepts与@Signature注解属性说明

可能有些新手使用mybatis拦截器的时候可能没太懂@Signature注解中type,method,args的用法首先mybatis可以拦截如下4中类型。

码码哈哈的博客 2万+

保姆级教程:用Python从UCI下载波士顿房价数据集,手把手跑通线性回归、岭回归和Lasso

本文提供了一份保姆级教程,详细讲解如何用Python从UCI下载波士顿房价数据集,并手把手实现线性回归、岭回归和Lasso回归模型。内容涵盖数据获取、清洗、特征分析到模型构建与评估的全流程,特别适合机器学习初学者掌握波士顿房价预测这一经典案例。

weixin_34254848的博客 476

Windows 10下用VS2022编译AFSIM 2.9.0的完整避坑指南

本文提供了在Windows 10系统下,使用Visual Studio 2022编译AFSIM 2.9.0仿真框架的详细指南。文章系统梳理了从环境准备、CMake配置、编译链接到安装打包的全流程,并重点针对编译过程中常见的文件编码、命名空间冲突等高频错误提供了具体解决方案,旨在帮助开发者高效避坑,顺利完成AFSIM在Windows平台上的构建。

weixin_28839549的博客 549

手写MyBatis第53弹: @Intercepts与@Signature注解的工作原理

本文深入解析MyBatis插件机制中的@Intercepts和@Signature注解,阐述其作为方法拦截导航系统的重要作用。文章从注解定义、工作原理到实战应用展开,重点解答了args属性在方法重载匹配中的必要性,并提供了SQL执行统计、参数加密等插件开发示例。同时给出多方法拦截策略和性能优化建议,最后总结开发高效稳定插件的关键要点,包括精确方法签名匹配和遵循最佳实践等。通过这两个注解的深度应用,可有效扩展MyBatis的能力边界。

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 1245

整车CAN网络错误帧排查方法

本文围绕 CAN 总线错误帧展开,先剖析其产生原因,涵盖物理连接与硬件问题、电磁兼容性问题、总线负载与设计问题及配置问题;再阐述位错误、填充错误等 5 类错误帧类型;接着说明错误帧与总线 BUSOFF 的关系,解析主动 / 被动错误状态及 BUSOFF 的触发与恢复;还结合整车故障案例做实际分析,指出错误帧根源多为线束或控制器问题。最后总结,强调错误帧是 CAN 协议保障高鲁棒性的机制,掌握相关知识助工程师提升 CAN 网络处理能力。

车载网络小D的博客 1247

手写MyBatis第54弹: @Intercepts与@Signature的读取与缓存策略

本文深入解析MyBatis拦截器注解机制,重点探讨了@Intercepts和@Signature注解的解析过程与优化策略。文章从注解解析的核心价值出发,分析了MyBatis采用的折中解析时机选择(在插件实例化后、首次包装前解析),详细介绍了注解解析的具体流程和缓存机制设计。为提升性能,MyBatis使用两级缓存结构(拦截器到签名映射缓存和类到接口缓存)和线程安全策略,并提供了减少反射调用、优化数据结构等实用技巧。通过实际应用案例和常见问题解决方案,帮助开发者深入理解MyBatis拦截器内部工作机制,实现高效

源码获取 | 运行部署 | 定制二开修改,如果回复不及时请耐心等待,请见谅。 834

LabVIEW多设备采集实战:1个程序同时控制3个RS485 Modbus仪表

本文详细介绍了如何使用LabVIEW实现多设备RS485 Modbus同步采集,涵盖硬件架构设计、多线程通信框架搭建、数据帧解析技巧及性能优化策略。通过实际项目案例,展示如何解决端口冲突、数据解析错误等工业自动化常见问题,提升采集系统实时性与可靠性。

qsc901234的博客 298

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

@Intercepts-mybatis拦截器

查询拦截器 package org.study.mybatis.config; import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.cache.CacheKey; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSq...

mingwulipo的博客 6620

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

Mybatis中@Intercepts、StatementHandler、ResultSetHandler用法记录,主要用于实现数据加解密

公司的海外业务中,有涉及数据隐私保护的要求。因此对于一些敏感数据,比如用户的姓名、地址、电话等,需要经过一层加密操作,才能把数据存到库中。因此,需要写一个方法实现在插入钱对数据进行加密。 方法如下: import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.xxxx.annotation.encrypt.EncryptEnabled; import com.xxxx.annotation

weixin_42891450的博客 956

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

mybatis:@Intercepts小例子(一)

这只是一个纯碎的mybatis的只针对@Intercepts应用的小列子,没有和spring做集成。 1.工作目录 2.数据库mysql,建立一个数据库表、实体对象User、UserMapper.java、UserMapper.xml省略。 使用mybatis自动代码生成工具生成:mybatis-generator-core-1.3.2。(此处略) 3.拦截器MyInterc...

aidixi8066的博客 2661

mybatis @Intercepts的用法1:修改sql语句

mybatis 的@Interceptor

tumu6889的博客 643

Mybatis自定义拦截器@Intercepts失效

mybatis自定义分页拦截器失效,没有执行

Lee的博客 4114

@Intercepts注解原理(mybatis拦截器)

MybatisAutoConfiguration初始化的时候,会在构造函数收集所有实现Interceptor接口的bean,在初始化SqlSessionFactory时,将Interceptor实例数组传入SqlSessionFactoryBean,再存入SqlSessionFactory的Configuration.interceptorChain,当执行mapper接口方法时,会走到InterceptorChain.pluginAll方法,形成类似责任链模式的数据结构,执行的时候按照责任链顺序执行

lyj的博客 862

mybatis @Intercepts的用法2:限制sql查询数量

Interceptor

tumu6889的博客 813

记录 有关MybatisPlusInterceptor里的addInnerInterceptor()方法和@Intercepts 都是怎么注入进去的

的addInnerInterceptor()方法添加了多个内部拦截器(实现了接口)是一个拦截器用了@Intercepts注解 的是相当于是一个拦截器, MybatisPlusInterceptor也是实现了Interceptor类的管理类而已。

zqx_7的博客 1097

MyBatis/mybatis_plus的项目 如何优雅地打印SQL

其中类上的Intercepts注解含义为:在 Executor 的 query、update 方法执行前后进行自定义的处理,其中Executor 是最底层的执行器,负责与数据库进行通信。平常像用的比较多的PageHelper,就是一个MyBatis的插件,实现原理和我们这次要做的功能十分相似。拦截过程中,如果存在拦截器,且方法的签名与拦截器配置的方法签名匹配,则调用拦截器的intercept方法。在参数少并且SQL简单的情况下,这样的SQL我们能通过手动去替换占位符,来获取到真正执行的SQL。

weixin_42471196的博客 2971
上一篇: mybatis #和$的区别
下一篇: mybatis collection和association
knife1220
博客等级 码龄15年 33粉丝 176原创
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值