MyBatis特殊字符转义拦截器问题针对(_、\、%)
作者:在奋斗的大道
这篇文章主要介绍了MyBatis特殊字符转义拦截器问题针对(_、\、%),具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
一、问题反馈
今天公司测试向我反馈,系统用户模糊查询功能在用户名称包含特殊字符时(_、\、%)无法正常查询结果。
二、问题验证
1、当like中包含_
时,查询仍为全部,即 like '%_%'
查询出来的结果与like '%%'
一致,并不能查询出实际字段中包含有_
特殊字符的结果条目
2、like中包括%
时,与1中相同
3、like中包含\
时,带入查询时,%\%
无法查询到包含字段中有\
的条目
三、问题解决思路
采用MyBatis 拦截器机制,处理模糊查询中包含特殊字符(_、\、%)
四、核心功能代码
4.1 MyBatis 特殊字符拦截器编写
package com.zzg.sql.interceptor; import java.util.HashMap; import java.util.Properties; import org.apache.ibatis.cache.CacheKey; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.mapping.SqlCommandType; 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.plugin.Signature; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; /** * 自定义拦截器方法,处理模糊查询中包含特殊字符(_、%、\) */ @Intercepts({ @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class }), @Signature(type = Executor.class, method = "query", args = { MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class }) }) public class EscapeInterceptor implements Interceptor { @Override public Object intercept(Invocation invocation) throws Throwable { // TODO Auto-generated method stub // 拦截sql Object[] args = invocation.getArgs(); MappedStatement statement = (MappedStatement) args[0]; // 请求参数对象 Object parameterObject = args[1]; // 获取 SQL SqlCommandType sqlCommandType = statement.getSqlCommandType(); if (SqlCommandType.SELECT.equals(sqlCommandType)) { if (parameterObject instanceof HashMap) { // 调用特殊字符处理方法 HashMap hash = (HashMap) parameterObject; hash.forEach((k, v) -> { // 仅拦截字符串类型且值不为空 if (v != null && v instanceof String) { String value = (String) v; value = value.replaceAll("\\\\", "\\\\\\\\"); value = value.replaceAll("_", "\\\\_"); value = value.replaceAll("%", "\\\\%"); // 请求参数对象HashMap重新赋值转义后的值 hash.put(k, value); } }); } } // 返回 return invocation.proceed(); } @Override public Object plugin(Object target) { // TODO Auto-generated method stub return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // TODO Auto-generated method stub } }
4.2 通过@Configuration标签
实例化EscapeInterceptor 拦截器。
package com.zzg.config; import java.util.Properties; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import com.zzg.sql.interceptor.EscapeInterceptor; import com.github.pagehelper.PageHelper; @Configuration public class MyBatisConfig { /** * mybatis 自定义拦截器(特殊字符处理) * @return */ @Bean public EscapeInterceptor getEscapeInterceptor(){ EscapeInterceptor interceptor = new EscapeInterceptor(); return interceptor; } /** * 分页对象实列化 * @return */ @Bean public PageHelper pageHelper() { PageHelper pageHelper = new PageHelper(); Properties p = new Properties(); p.setProperty("offsetAsPageNum", "true"); p.setProperty("rowBoundsWithCount", "true"); p.setProperty("reasonable", "true"); p.setProperty("dialect", "mysql"); pageHelper.setProperties(p); return pageHelper; } }
效果展示:
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。