您的位置:首页 > 其它

Hql语句模糊查询‘like’与中文问题

2015-02-04 17:46 399 查看
在做搜索日志的关键字中遇到的问题,特此记录下来:



首先遇到的问题是模糊查询时HQL拼写错误

尝试了几次后终于搞定,hql如下:

String hql = " and (log.resourceName like '%"+ searchValue +"%'"
+ " or log.user like '%"+ searchValue + "%'"
+ " or log.time like '%"+ searchValue + "%'"
+ " or log.operation like '%"+ searchValue + "%'"
+ " or log.result like '%"+ searchValue + "%')";


[b]※ 这里必须注意只能使用单引号,如:" '%" + name + "%' "[/b]
like语法简介:

% 表示任意个数的任意字符
_ 表示任意一个字符
[abcdefg] 表示里面的字符任何一个,只取一个
[^c] 表示里面的字符不包含c
[a-z] 表示区间中的任一个,如c或d等
[^a-z] 表示非区间中的任一个
escape '/' 转义符,表示/之后的字符不是特殊字符。



接下来遇到的问题是request取得的值含有中文的话产生乱码

经过一番查阅之后才明白其原理如下:
http请求是以ISO-8859-1的编码来传送url的,如果页面的content-type为utf-8 ,那么在发送请求时,会将字符转成utf-8后进行传送。

服务器收到这个字节流,默认会以ISO-8859-1来将这个字节流还原成相应的字符串,就如同这样:

服务器:cc = new String(bb,"ISO-8859-1");

客户端:bb = aa.getBytes("UTF-8");

还原字节流为节符串:request.getParameter("");

获取到这个cc,那么cc当然乱码了;

所以就产生了这样的做法:new String(request.getParameter("").getBytes("ISO-8859-1"),"UTF-8")还原成原始字符串。



String search = request.getParameter("search[value]");
String searchValue = new String(search.getBytes("ISO-8859-1"),"UTF-8");




最后遇到的问题是模糊查询中中文与数据库时间类型抛异常

中文正确了,却在模糊查询时却报异常java.sql.SQLException:Illegal mix of collations for operation 'like' ,真是醉了,又怎么不对了腻?!

以下内容copy网友的方法,因为本人试用后仍抛该异常,未能解决问题,so.....

我果断判断了下请求的参数是否为中文,若为中文则不对time、date、datetime此三种类型的字段进行模糊查询。

判断中文isChinese()方法见文章最后的代码。

对于我的非常规做法,仅供参考。欢迎评论、交流。

错误原理分析以及错误解决方法:

这是什么情况呢?查询一番后发现是数据库字段类型的问题:

从SQL语句方面分析这个问题,发现是 log.time like '%中文%' 导致整个SQL语句执行报错;

在 MySQL 5.5 以上, 若字段 Type 是 time,date,datetime,在 select 時若使用 like '%中文%' 会出現 Illegal mix of collations for operation 'like'

因此必需改成like binary '%中文%'即可避免出现错误。

到此该问题终于解决了,真是一路坎坷啊!附上判断是否为中文的代码:

public class IsChineseUtil {

// GENERAL_PUNCTUATION 判断中文的“号
// CJK_SYMBOLS_AND_PUNCTUATION 判断中文的。号
// HALFWIDTH_AND_FULLWIDTH_FORMS 判断中文的,号
private static final boolean isChinese(char c) {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
|| ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
|| ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
|| ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
return true;
}
return false;
}

public static final boolean isChinese(String strName) {
char[] ch = strName.toCharArray();
for (int i = 0; i < ch.length; i++) {
char c = ch[i];
if (isChinese(c)) {
return true;
}
}
return false;
}

public static void main(String[] args) {
System.out.println(isChinese("き"));
System.out.println(isChinese("test,.?!%^&*(){}[]"));
System.out.println(isChinese("测试"));
System.out.println(isChinese("“测试”,。?!%……&*()——{}【】”"));
}

public static final boolean isChineseCharacter(String chineseStr) {
char[] charArray = chineseStr.toCharArray();
for (int i = 0; i < charArray.length; i++) {
if ((charArray[i] >= 0x4e00) && (charArray[i] <= 0x9fbb)) {
return true;
}
}
return false;
}

/**
* @deprecated; 弃用。和方法isChineseCharacter比效率太低。
* */
public static final boolean isChineseCharacter_f2() {
String str = "!?";
for (int i = 0; i < str.length(); i++) {
if (str.substring(i, i + 1).matches("[\\u4e00-\\u9fbb]+")) {
return true;
}
}
return false;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: