MyBatis特殊字符转义拦截器问题针对(_、\、%)

2023-02-07 15:37:10

目录一、问题反馈二、问题验证三、问题解决思路四、核心功能代码4.1MyBatis特殊字符拦截器编写4.2通过@Configuration标签总结一、问题反馈今天公司测试向我反馈,系统用户模糊查询...

目录
一、问题反馈
二、问题验证
三、问题解决思路
四、核心功能代码
4.1 MyBATis 特殊字符拦截器编写
4.2 通过@Configuration标签
总结

一、问题反馈

今天公司测试向我反馈,系统用户模糊查询功能在用户名称包含特殊字符时(_、\、%)无法正常查询结果。

二、问题验证

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;
}
}

效果展示:

MyBatis特殊字符转义拦截器问题针对(_、\、%)

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。