傳統的解決思路:自定義一個攔截器,當有模糊查詢時,模糊查詢的關鍵字中包含有上述特殊字符時,在該特殊字符前添加
\
進行轉義處理。新的解決思路:將like 替換為 MySQL內置函數locate函數
參考博客:
https://www.jianshu.com/p/f4d3e6ffeee8
https://www.cnblogs.com/tommy-huang/p/4483583.html
一、問題提出
使用MyBatis中的模糊查詢時,當查詢關鍵字中包括有_
、\
、%
時,查詢關鍵字失效。
二、問題分析
1、當like中包含_
時,查詢仍為全部,即 like '%_%'
查詢出來的結果與like '%%'
一致,並不能查詢出實際字段中包含有_
特殊字符的結果條目
2、like中包括%
時,與1中相同
3、like中包含\
時,帶入查詢時,%\%
無法查詢到包含字段中有\
的條目
特殊字符 | 未處理 | 處理后 |
---|---|---|
_ | like '%_%' |
like '%\_%' |
% | like '%%%' |
like '%\%%' |
\ | like '%\%' |
`like '%\%' |
ESCAPE '/'
必須加在SQL的最后。like '%\_%'
效果與like concat('%', '\_', '%')
相同
三、問題解決
1、自定義攔截器方法類
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.keyidea.boss.utils.EscapeUtil; import org.apache.ibatis.executor.Executor; import org.apache.ibatis.mapping.BoundSql; import org.apache.ibatis.mapping.MappedStatement; import org.apache.ibatis.plugin.*; import org.apache.ibatis.session.ResultHandler; import org.apache.ibatis.session.RowBounds; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.HashSet; import java.util.Properties; import java.util.Set; /** * 自定義攔截器方法,處理模糊查詢中包含特殊字符(_、%、\) */ @Intercepts(@Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class})) public class MyInterceptor implements Interceptor { Logger LOGGER = LoggerFactory.getLogger(MyInterceptor.class); @Override public Object intercept(Invocation invocation) throws Throwable { // 攔截sql Object[] args = invocation.getArgs(); MappedStatement statement = (MappedStatement)args[0]; Object parameterObject = args[1]; BoundSql boundSql = statement.getBoundSql(parameterObject); String sql = boundSql.getSql(); // 處理特殊字符 modifyLikeSql(sql, parameterObject, boundSql); // 返回 return invocation.proceed(); } @Override public Object plugin(Object target) { return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { } @SuppressWarnings("unchecked") public