今天收到一个需求,根据请求方的不同,动态的切换表名(涵盖SELECT,INSERT,UPDATE操作)。几张新表和旧表的结构完全一致,但是分开维护。看到需求第一反应是将表名提出来当${tableName}参数,然后AOP拦截判断再替换表名。但是后面看了一下这几张表在很多mapper接口都有使用,其中还有一些复杂的连接查询,提取tableName当参数肯定是不现实的了。后面和组内大佬讨论之后,发现可以使用MyBatis提供的拦截器,判断并且动态的替换表名。
一、Mybatis Interceptor 拦截器接口和注解简单的说就是mybatis在执行sql的时候,拦截目标方法并且在前后加上我们的业务逻辑。实际上就是加@Intercepts注解和实现org.apache.ibatis.plugin.Interceptor接口
二、实现思路 在intercept方法中有参数Invocation对象,里面有3个成员变量和@Signature对应 成员变量变量类型说明targetObject代理对象methodMethod被拦截方法argsObject[]被拦截方法执行所需的参数 通过Invocation中的args变量。我们能拿到MappedStatement这个对象(args[0]),传入sql语句的参数Object(args[1])。而MappedStatement是一个记录了sql语句(sqlSource对象)、参数值结构、返回值结构、mapper配置等的一个对象。sqlSource对象和传入sql语句的参数对象Object就能获得BoundSql。BoundSql的toString方法就能获取到有占位符的sql语句了,我们的业务逻辑就能在这里介入。获取到sql语句,根据规则替换表名,塞回BoundSql对象中、再把BoundSql对象塞回MappedStatement对象中。最后再赋值给args[0](实际被拦截方法所需的参数)就搞定了 三、代码实现 四、运行结果 写在最后一开始接到这个需求的时候,会习惯性的从熟悉常用的技术入手。如果涉及的表引用没这么多,是不是就会直接用AOP拦截判断替换了呢,我大概率是会的。可能就不会想到上面的拦截器动态替换的方法(相当于失去一次学习的机会),还是要跳出惯性多思考还有没有更合适的做法,把每次需求都当成一次学习的机会,舒适圈都能变开阔很多,共勉。
参考资料MyBatis官网
mybatis插件实现自定义改写表名
到此这篇关于MyBatis拦截器动态替换表名的文章就介绍到这了,更多相关MyBatis动态替换表名内容请搜索七叶笔记以前的文章或继续浏览下面的相关文章希望大家以后多多支持七叶笔记!