- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
第
使用Mybatis自定义插件实现不侵入业务的公共参数自动追加
后台业务开发的过程中,往往会遇到这种场景:需要记录每条记录产生时间、修改时间、修改人及添加人,在查询时查询出来。
以往的做法通常是手动在每个业务逻辑里耦合上这么一块代码,也有更优雅一点的做法是写一个拦截器,然后在Mybatis拦截器中为实体对象中的公共参数进行赋值,但最终依然需要在业务SQL上手动添加上这几个参数,很多开源后台项目都有类似做法。
这种做法往往不够灵活,新增或修改字段时每处业务逻辑都需要同步修改,业务量大的话这么改非常麻烦。
最近在我自己的项目中写了一个Mybatis插件,这个插件能够实现不修改任何业务逻辑就能实现添加或修改时数据库公共字段的赋值,并能在查询时自动查询出来。
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的上下文参数后继续执行。
在MybAIts的拦截器中,可以拿到MappedStatement对象,这里面包含了一次数据库操作的原始SQL以及实体对象与结果集的映射关系,为了实现公共参数自动携带,我们就需要在拦截器中修改原始SQL:
Insert操作:自动为Insert语句添加公共字段并赋值
Update操作:自动为Update语句添加公共字段并赋值
Select操作:自动为Select语句的查询参数上添加上公共字段
以及修改实体对象与结果集的映射关系,做到自动修改查询语句添加公共字段后能够使Mybatis将查出的公共字段值赋给实体类。
简单来说就是修改MappedStatement中的SqlSource以及ResultMap
修改SqlSource
在SqlSource中,包含了原始待执行的SQL,需要将它修改为携带公共参数的SQL。
需要注意的是Mybatis的SqlSource、ResultMap中的属性仅允许初次构造SqlSource对象时进行赋值,后续如果需要修改只能通过反射或者新构造一个对象替换旧对象的方式进行内部参数修改。
直接贴出来代码,这里新构造了SqlSource对象,在里面实现了原始SQL的解析修改:
SQL的动态修改使用了JSQLParser将原始SQL解析为AST抽象语法树后做参数追加,之后重新解析为SQL,使用自定义SqlSource返回修改后的SQL实现SQL修改
staticclassModifiedSqlSourceV2implementsSqlSource{
privatefinalMappedStatementmappedStatement;
privatefinalConfigurationconfiguration;
publicModifiedSqlSourceV2(MappedStatementmappedStatement,Configurationconfiguration){
this.mappedStatement=mappedStatement;
this.configuration=configuration;
@Override
publicBoundSqlgetBoundSql(ObjectparameterObject){
//获取原始的BoundSql对象
BoundSqloriginalBoundSql=mappedStatement.getSqlSource().getBoundSql(parameterObject);
//获取原始的SQL字符串
StringoriginalSql=originalBoundSql.getSql();
log.debug(公共参数添加-修改前SQL:{},ori
文档评论(0)