Mybatis拦截器实现带参数SQL语句打印
前言
在我们工作实际项目中,常常遇到使用Mybatis作为ORM框架,在使用的过程中,一般都会开启日志的打印功能,这样在控制台就会输出执行的SQL,定位SQL问题也是比较方便的。但是,我们就会发现,这样打印出来的SQL是预编译语句和参数是分开的。
此时如果需要去数据库执行上条SQL的时候,我们需要手动的把参数拼接到SQL语句中;参数少此操作还可以,参数一旦比较多,此操作相当的麻烦繁琐。下面我们就使用Mybatis拦截器的方式来实现打印完整SQL的功能。具体实现实现拦截器逻辑importlombok。extern。slf4j。Slf4j;importorg。apache。ibatis。cache。CacheKey;importorg。apache。ibatis。executor。Executor;importorg。apache。ibatis。mapping。BoundSql;importorg。apache。ibatis。mapping。MappedStatement;importorg。apache。ibatis。mapping。ParameterMapping;importorg。apache。ibatis。plugin。;importorg。apache。ibatis。reflection。MetaObject;importorg。apache。ibatis。session。Configuration;importorg。apache。ibatis。session。ResultHandler;importorg。apache。ibatis。session。RowBounds;importorg。apache。ibatis。type。TypeHandlerRegistry;importorg。springframework。util。CollectionUtils;importjava。text。DateFormat;importjava。util。Date;importjava。util。List;importjava。util。Locale;importjava。util。Properties;importjava。util。regex。Matcher;author公众号:SimpleMemoryversion1。0。0ClassNameFullSQLInterceptor。javaDescriptionTODOcreateTime2022年10月14日18:39:00Slf4jIntercepts(value{Signature(typeExecutor。class,methodupdate,args{MappedStatement。class,Object。class}),Signature(typeExecutor。class,methodquery,args{MappedStatement。class,Object。class,RowBounds。class,ResultHandler。class,CacheKey。class,BoundSql。class}),Signature(typeExecutor。class,methodquery,args{MappedStatement。class,Object。class,RowBounds。class,ResultHandler。class})})publicclassMybatisSQLInterceptorimplementsInterceptor{OverridepublicObjectintercept(Invocationinvocation)throwsThrowable{try{获取xml中的一个selectupdateinsertdelete节点,主要描述的是一条SQL语句MappedStatementmappedStatement(MappedStatement)invocation。getArgs()〔0〕;Objectparameternull;获取参数,if语句成立,表示sql语句有参数,参数格式是map形式if(invocation。getArgs()。length1){parameterinvocation。getArgs()〔1〕;log。error(sqlparam:{},parameter);}if(SqlCommandType。SELECT。equals(mappedStatement。getSqlCommandType())){}获取到节点的id,即sql语句的idStringsqlIdmappedStatement。getId();BoundSql就是封装myBatis最终产生的sql类BoundSqlboundSqlmappedStatement。getBoundSql(parameter);获取节点的配置ConfigurationconfigurationmappedStatement。getConfiguration();获取到最终的sql语句StringsqlgetSql(configuration,boundSql,sqlId);log。error(sql{},sql);}catch(Exceptione){}执行完上面的任务后,不改变原有的sql执行过程returninvocation。proceed();}封装了一下sql语句,使得结果返回完整xml路径下的sql语句节点idsql语句paramconfigurationconfigurationparamboundSqlboundSqlparamsqlIdsqlIdreturnjava。lang。StringpublicstaticStringgetSql(Configurationconfiguration,BoundSqlboundSql,StringsqlId){StringsqlshowSql(configuration,boundSql);StringBuilderstrnewStringBuilder(100);str。append(sqlId);str。append(:);str。append(sql);returnstr。toString();}如果参数是String,则添加单引号,如果是日期,则转换为时间格式器并加单引号;对参数是null和不是null的情况作了处理paramobjobjreturnjava。lang。StringprivatestaticStringgetParameterValue(Objectobj){Stringvaluenull;if(objinstanceofString){valueobj。toString();}elseif(objinstanceofDate){DateFormatformatterDateFormat。getDateTimeInstance(DateFormat。DEFAULT,DateFormat。DEFAULT,Locale。CHINA);valueformatter。format(newDate());}else{if(obj!null){valueobj。toString();}else{value;}}returnvalue;}进行?的替换paramconfigurationparamboundSqlreturnpublicstaticStringshowSql(Configurationconfiguration,BoundSqlboundSql){ObjectparameterObjectboundSql。getParameterObject();获取参数ListParameterMappingparameterMappingsboundSql。getParameterMappings();StringsqlboundSql。getSql()。replaceAll(〔s〕,);sql语句中多个空格都用一个空格代替if(!CollectionUtils。isEmpty(parameterMappings)parameterObject!null){TypeHandlerRegistrytypeHandlerRegistryconfiguration。getTypeHandlerRegistry();获取类型处理器注册器,类型处理器的功能是进行java类型和数据库类型的转换
如果根据parameterObject。getClass()可以找到对应的类型,则替换if(typeHandlerRegistry。hasTypeHandler(parameterObject。getClass())){sqlsql。replaceFirst(?,Matcher。quoteReplacement(getParameterValue(parameterObject)));}else{MetaObjectmetaObjectconfiguration。newMetaObject(parameterObject);MetaObject主要是封装了originalObject对象,提供了get和set的方法用于获取和设置originalObject的属性值,主要支持对JavaBean、Collection、Map三种类型对象的操作for(ParameterMappingparameterMapping:parameterMappings){StringpropertyNameparameterMapping。getProperty();if(metaObject。hasGetter(propertyName)){ObjectobjmetaObject。getValue(propertyName);sqlsql。replaceFirst(?,Matcher。quoteReplacement(getParameterValue(obj)));}elseif(boundSql。hasAdditionalParameter(propertyName)){ObjectobjboundSql。getAdditionalParameter(propertyName);该分支是动态sqlsqlsql。replaceFirst(?,Matcher。quoteReplacement(getParameterValue(obj)));}else{sqlsql。replaceFirst(?,缺失);}打印出缺失,提醒该参数缺失并防止错位}}}returnsql;}OverridepublicObjectplugin(Objecttarget){returnPlugin。wrap(target,this);}OverridepublicvoidsetProperties(Propertiesproperties){}}
配置拦截器
在Mybatis的配置文件中配置拦截器
pluginsplugininterceptorcom。ruoyi。web。config。MybatisSQLInterceptorpluginplugins
在application。yml中配置Mybatis的全局的配置文件mybatisconfig。xml
实现效果
启动项目,查看控制台打印SQL语句情况。
2022101509:51:50。780ERROR30292〔io8089exec24〕c。r。web。config。MybatisSQLInterceptor:sqlcom。ruoyi。system。mapper。SysDeptMapper。selectDeptList:selectd。deptid,d。parentid,d。ancestors,d。deptname,d。ordernum,d。leader,d。phone,d。email,d。status,d。delflag,d。createby,d。createtimefromsysdeptdwhered。delflag0ANDdeptnamelikeconcat(,开发,)ANDstatus0orderbyd。parentid,d。ordernum
公众号:SimpleMemory
三千元内高性价比办公本中柏EZbookX7全面评测在我们的后台,经常有网友留言表示,想要花近可能低的预算购买一台笔记本进行轻度的办公、聊天,上网看看视频。但是看看电商平台上,低价的笔记本往往是一些不靠谱的第三方店铺在卖,而淘一……
映泰推出B760TITX规格映泰现推出了新款采用B760芯片的主板,型号为B760TSILVER主板,支持英特尔酷睿第12代和第13代处理器。B760TSILVER主板采用MiniITX规格,主板尺……
看红火,赏烟花!清徐元宵节活动全攻略出炉!欢乐中国年奋进新征程清徐元宵节民间文艺展演及烟花表演即将盛大启幕为了让广大市民及游客获得安全愉快的活动体验度过一个热闹喜庆的元宵节请提前留意以下展……
焦作国保档案第1集窄涧谷太平寺石窟【来源:焦作市文化广电和旅游局新闻资讯】焦作古称覃怀,又称怀川,地处中原文明核心区,是中华文明的重要发祥地之一,现存全国重点文物保护单位28处。为了宣传展示焦作厚重的历史……
煤化工蝶变以氢代煤焕发新机本报记者陈家运北京报道在双碳背景下,煤化工通过与绿氢耦合焕发新机。近日,煤化工龙头宝丰能源(600989。SH)公开透露,其位于内蒙古鄂尔多斯市的绿氢煤制烯烃项目一……
钾的几个神奇好处,知道这些或许会对你有帮助相信很多小伙伴都知道,我们身体里的钾元素有保健心脏、血糖、保护肾脏等好处。还有一些神奇的好处你也应该要知道。研究表明,我们一个正常人的身体每天需要4000多毫克。其他微量……
二十四扫房子,家有孕妇,年底大扫除要注意这些问题文咩小胖俗语说二十四扫房子,通常在腊月二十四前后,大家就开始忙着洗洗涮涮,把家里的卫生彻底清扫一下。年底家庭大扫除,包括地面的清扫、柜子窗户等的擦拭,以及床单被褥、……
爆炒螺丝的家常做法,不输夜市大排档,好吃到停不下来大家好,我是懒惰的小厨娘!三月螺,赛肥鹅,又到了吃田螺的时候,作为一个热爱嗦螺的人,这必须得安排上,晚上和我爸喝酒,来一碟子,真的是太过瘾了!今天我就把我们家常做的……
勐巴拉小镇用特色旅游小镇打造勐海康养旅居名片【来源:西双版纳文化旅游局新闻发布】近年来,勐海县依托优越的生态环境、独特的雨林景观、宜人的气候、多彩的民族风情,着力发展以康养度假旅居为主题的现代化旅游产业,打造宜居宜……
抗日神剧乱象,何时可以休说到抗日神剧,你可以想到什么手撕鬼子的武侠人士,裤裆藏雷的女兵,自行车扒火车的铁道游击队,打不死的燕双鹰,竹筒迫击炮,包子炸弹,用加特林突突的皮甲中年男人,一场战役下来依……
四川的天空之城色达,此生必去的红川西佛国秘境!如果去不了天堂,那就去色达吧!一生必去的红色佛国,离天堂最近的地方,也是朝圣之旅的终点。四川色达,一个缺氧,但不缺信仰的地方,群山之中的那一抹红,成为内心深处最向往的地方……
华尔街日报评论文章瑞信面临破产,瑞士正陷入自二战以来最严重的【文观察者网熊超然】上周,瑞士信贷集团(CreditSuisse)游走于暴雷的边界,为阻止银行业危机蔓延,瑞士政府出面斡旋,推动了本国两家最大银行的收购交易案瑞银集团(UBS)……