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

在做搜索日志的关键字中遇到的问题,特此记录下来:

  • 首先遇到的问题是模糊查询时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 + "%')";

※ 这里必须注意只能使用单引号,如:'%" + name + "%' "

like语法简介:

  1. %    表示任意个数的任意字符
  2. _    表示任意一个字符
  3. [abcdefg]   表示里面的字符任何一个,只取一个
  4. [^c]           表示里面的字符不包含c
  5. [a-z]          表示区间中的任一个,如c或d等
  6. [^a-z]        表示非区间中的任一个
  7. 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;
        }
}



  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值