绵阳网站建设网站建设,wordpress安装主题教程,wordpress 页面文章,wap网站生成app一、问题背景
系统测试过程中#xff0c;测试同学反馈搜索框输入%或_进行模糊查询后#xff0c;查询结果不正确#xff1b;搜索期望结果是仅包含%或_的记录。
二、原因
模糊查询是一种通过模糊条件来匹配数据库中数据的…一、问题背景
系统测试过程中测试同学反馈搜索框输入%或_进行模糊查询后查询结果不正确搜索期望结果是仅包含%或_的记录。
二、原因
模糊查询是一种通过模糊条件来匹配数据库中数据的查询方法通常会使用以下两种通配符进行数据匹配。
% 表示零个或多个字符。例如%cat% 匹配包含 cat 的任何字符串。_ 表示一个单一的字符。例如h_t 匹配 hat、hot 等。
如果没对通配符进行处理而直接进行查询时它代表的特殊含义将会使得查询结果不正确。
三、解决思路
想要查询包含 %或_ 字符的字段值但又不希望它们被解释为通配符时可以使用转义字符\ (在MySQL中默认使用\用作转义字符)来取消这些字符的特殊含义。
四、解决方法
1、\ 反斜杠转义
这里我封装好了一个工具类当某个查询条件需要进行模糊查询时先对查询条件进行预处理然后再塞到SQL中。
1工具类代码
import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers;public class SqlLikeUtil {private static final char MYSQL_WILDCARD_PERCENTAGE %;private static final char MYSQL_WILDCARD_UNDERSCORE _;private static final char MYSQL_DEFAULT_ESCAPE \\;private static final char[] MYSQL_WILDCARDS new char[]{%, _, \\};public SqlLikeUtil() {}public static String genMysqlLikedString(String str) {return genMysqlLikedString(str, true, true);}public static String genMysqlLikedPrefixString(String str) {return genMysqlLikedString(str, true, false);}public static String genMysqlLikedString(String str, boolean prefixMatch, boolean suffixMatch) {if (str null) {return null;} else {String escaped escapeChars(MYSQL_WILDCARDS, \\, str);StringBuilder builder new StringBuilder();if (suffixMatch) {builder.append(%);}builder.append(escaped);if (prefixMatch) {builder.append(%);}return builder.toString();}}private static String escapeChars(char[] chars, char escape, String str) {if (chars ! null chars.length ! 0 str ! null) {Escapers.Builder builder Escapers.builder();char[] var4 chars;int var5 chars.length;for(int var6 0; var6 var5; var6) {char c var4[var6];String replacement new String(new char[]{escape, c});builder.addEscape(c, replacement);}Escaper escaper builder.build();String result escaper.escape(str);return result;} else {return str;}}} 代码逻辑解释创建转义器对象将%, _, \\ 加入到转义器使用这个转义器即可对字段值进行特殊字符的转义。 这里重点说明一下数据库中的\在Java代码中要表示为 \\其次为什么我们需要对 \\ 也进行转义。 如果我们的查询条件为name \但此时并未对其进行转义那么对应的SQL应为 select * from test where name like %\%; 这段SQL的查询含义为查询任意字符开头以%结尾的值与我们设想的不符正确的SQL应为 select * from test where name like %\\%;这样 \ 就可被作为普通字符进行查询了。 2使用示例
String name SqlLikeUtil.genMysqlLikedString(req.getName()); 注上述SqlLikeUtil.genMysqlLikedString()方法的调用会使得name值前后被 % 包围所以我们在使用like进行查询条件拼接时只需直接取值即可如果想对字段值前后拼接%进行控制可以调用genMysqlLikedString()重载的方法指定前缀、后缀。 2、指定转义字符进行转义
在解决问题的过程中我发现并不是只可以使用 \ 进行转义可以使用ESCAPE关键字在SQL中指定转义字符。 ESCAPE 是一个用于指定转义字符的关键字ESCAPE 关键字允许你指定一个转义字符用于转义模糊查询中的特殊字符。比如在模糊查询中使用了 ESCAPE /这意味着斜杠 / 被指定为转义字符。在这个例子中%/_ 表示任意字符和任意单个字符而 ESCAPE / 指定了斜杠 / 为转义字符。因此/% 和 /_ 会被解释为普通字符而不是通配符。 1工具类代码
import com.google.common.escape.Escaper;
import com.google.common.escape.Escapers;public class SqlLikeUtil {private static final char MYSQL_WILDCARD_PERCENTAGE %;private static final char MYSQL_WILDCARD_UNDERSCORE _;private static final char MYSQL_DEFAULT_ESCAPE \\;private static final char[] MYSQL_WILDCARDS new char[]{%, _, /};public SqlLikeUtil() {}public static String genMysqlLikedString(String str) {return genMysqlLikedString(str, true, true);}public static String genMysqlLikedPrefixString(String str) {return genMysqlLikedString(str, true, false);}public static String genMysqlLikedString(String str, boolean prefixMatch, boolean suffixMatch) {if (str null) {return null;} else {String escaped escapeChars(MYSQL_WILDCARDS, /, str);StringBuilder builder new StringBuilder();if (suffixMatch) {builder.append(%);}builder.append(escaped);if (prefixMatch) {builder.append(%);}return builder.toString();}}private static String escapeChars(char[] chars, char escape, String str) {if (chars ! null chars.length ! 0 str ! null) {Escapers.Builder builder Escapers.builder();char[] var4 chars;int var5 chars.length;for(int var6 0; var6 var5; var6) {char c var4[var6];String replacement new String(new char[]{escape, c});builder.addEscape(c, replacement);}Escaper escaper builder.build();String result escaper.escape(str);return result;} else {return str;}}} 说明与使用 \ 进行转义不同的是在使用工具类对查询条件转义后还需要在SQL中加ESCAPE /例如where name like #{name} ESCAPE /。 如果没有其他场景要求的话使用\进行转义更方便。 最后 SqlLikeUtil工具类可能不太完善但可以给大家提供一个思路大家可以根据自己的实际想法与需求完善这个工具类希望我的思路可以帮到大家~