1.mysql数据库里的nickname字段内容是经过unicode编码处理后存储的,
如:\u73\u74\u61\u72\u7a\u6d\ud83d\udc7f\u20\ud83d\ude04\u20\ud83d\ude03\u20\ud83d\ude13
实际明文:starzm? ? ? ?
每个字符都是以\u开头的,后面跟上2或4位的16进制表示的字符。
注意:有些转义识别工具,在遇到2位带字母(大小超过十进制10)的16进制字符,会出错,需要在16进制数字前补足两个0,达到4位16进制数,才能正常识别解码,如:
https://www.css-js.com/tools/unicode.html 和 http://tool.chinaz.com/tools/unicode.aspx
但是mysql中对unicode识别时没有此要求。
2.目标是使用模糊匹配按nickname模糊查找
(1)在使用mybatis查mysql数据库之前对nickname处理:
//加密成mysql数据库能识别的unicode码
public static String encodeToMysqlUnicode(String string) {
StringBuffer unicode = new StringBuffer();
for (int i = 0; i < string.length(); i++) {
// 取出每一个字符
char c = string.charAt(i);
// 转换为unicode
unicode.append("\\u" + Integer.toHexString(c));
}
return unicode.toString();
}
(2)直接在navicat(连mysql的客户端)测试时发现,where条件中需要
nickname like concat('%',"\u73\\\\u74\\\\u61\\\\u72\\\\u7a\\\\u6d",'%')
才能正常查出数据。
其中\u73表示starzm中的字一个字符s,表示后续其他字符unicode编码则需要多层转义,带4个反斜杠。
此外,\u73也可使用双斜杠即\\u73,也即
nickname like concat('%',"\\u73\\\\u74\\\\u61\\\\u72\\\\u7a\\\\u6d",'%')
完整sql:
select * from tab_user_fans where
nickname like concat('%',"starzm",'%') or nickname like concat('%',"\u73\\\\u74\\\\u61\\\\u72\\\\u7a\\\\u6d",'%')
order by REGIST_TIME desc limit 0,10
(此sql只支持navicat直接查mysql数据库,但不支持程序通过mybatis查数据库)
(3)但是在程序里使用此sql查不出数据,但是上一步在navicat同样的sql能查出数据,奇怪!
项目框架Struts+Spring+mybatis,sql写在xml配置文件里
猜测也应该是mybatis连mysql后使用此sql查的时候,有编码转义之类的,导致查不出来数据。
解决办法:
把反斜杠\改成下划线_
改入库查出之前对nickname处理逻辑,把\\u改成_u即可
//加密成mysql数据库能识别的unicode码
public static String encodeToMysqlUnicode(String string) {
StringBuffer unicode = new StringBuffer();
for (int i = 0; i < string.length(); i++) {
// 取出每一个字符
char c = string.charAt(i);
// 转换为unicode
unicode.append("_u" + Integer.toHexString(c));
}
return unicode.toString();
}
新的sql:
select * from tab_user_fans where
nickname like concat('%',"starzm",'%') or nickname like concat('%',"_u73_u74_u61_u72_u7a_u6d",'%')
order by REGIST_TIME desc limit 0,10
此sql即支持navicat直接查mysql数据库,也支持程序通过mybatis查mysql数据库!
完美解决!
应该是mybatis底层编码支持问题,直接使用navicat查mysql数据库就没有上述unicode编码问题。