通知 网站从因情语写改为晴雨,这个网站的模板也从calmlog_ex改为 whimurmur

多字段非连续模糊查询java实现

378人浏览 / 0人评论 / | 作者:因情语写  | 分类: JAVA基础  | 标签: JAVA  | 

作者:因情语写

链接:https://www.proprogrammar.com/article/285

声明:请尊重原作者的劳动,如需转载请注明出处


       工作需要,写了一个实现数据库多字段模糊查询的方法,背景是输入用户的信息,如用户的userid,姓名,拼音等,可以查出相关的用户

  具体如下

  1. 操作一张表,可以设置表前缀

  2. 可以实现中文的不连续查询(如通过输入中国可以查出中华人民共和国)

  3. 可以实现以输入文字开头的字段的查询

  4. 可以实现包含输入文字的字段的查询

  5. 可以自定义是否加and前缀

  6. 可以实现大小写不敏感的查询

  7. 可以实现预编译的查询语句

  不多说,上代码

/**
     * 构建一个不连续文字的模糊查询语句:如通过手资可以查到手术资料
     * @param searchStr    检索字符串
     * @param tabPrefix 表前缀
     * @param likeFields 比较字段
     * @param preAnd 是否在语句前加and
     * @param chineseDisContinuousSearch 检索内容含中文才进行不连续查询,否则进行连续查询
     * @param startMatch 检索是否从字段开头进行匹配
     * @param isPreparedStatement 是否是预编译语句(将参数用?代替)
     * @return
     */
    public static String buildProFuzzySearch(String searchStr, String tabPrefix, String[] likeFields, 
      boolean preAnd, boolean chineseDisContinuousSearch, boolean startMatch, boolean isPreparedStatement)
    {
        
        StringBuilder result = new StringBuilder();
        StringBuilder tempBuilder = new StringBuilder();
        if(StringUtils.isNotEmpty(searchStr) && null != likeFields && likeFields.length > 0)
        {
            if(preAnd)
            {
                result.append("and ");
            }
            
            result.append("(");
            searchStr = searchStr.toUpperCase();
            
            if(!chineseDisContinuousSearch || !isContainChinese(searchStr))//chineseDisContinuousSearch为false或者不包含中文(连续查询)
            {
                for(int i = 0, length = likeFields.length; i < length; i++)
                {
                    if(tempBuilder.length() > 0)
                    {
                        tempBuilder.append("or ");
                    }
                    
                    tempBuilder.append("UPPER(");
                    
                    if(StringUtils.isNotEmpty(tabPrefix))
                    {
                        tempBuilder.append(tabPrefix).append(".");
                    }
                    
                    tempBuilder.append(likeFields[i]).append(") ").append("like ");
                    if(isPreparedStatement)
                    {
                        tempBuilder.append("? ");
                    }
                    else
                    {
                        if(startMatch)
                        {
                            tempBuilder.append("'");
                        }
                        else
                        {
                            tempBuilder.append("'%");
                        }
                        tempBuilder.append(searchStr).append("%' ");
                    }
                }
            }
            else//chineseDisContinuousSearch为ture且包含中文时(不连续查询)
            {
                for(int i = 0, length = likeFields.length; i < length; i++)
                {
                    if(tempBuilder.length() > 0)
                    {
                        tempBuilder.append("or ");
                    }
                    
                    tempBuilder.append("UPPER(");
                    
                    if(StringUtils.isNotEmpty(tabPrefix))
                    {
                        tempBuilder.append(tabPrefix).append(".");
                    }
                    
                    tempBuilder.append(likeFields[i]).append(") ").append("like ");
                    if(isPreparedStatement)
                    {
                        tempBuilder.append("? ");
                    }
                    else
                    {
                        char[] searchChars = searchStr.toCharArray();
                        tempBuilder.append("'%");
                        for(int j = 0, charLength = searchChars.length; j < charLength; j++)
                        {
                            tempBuilder.append(String.valueOf(searchChars[j])).append("%");
                        }
                        tempBuilder.append("' ");
                    }
                }
            }
            
            result.append(tempBuilder.toString());
            result.append(")");
        }
        
        return result.toString();
    }    

  public static boolean isContainChinese(String str) {
         
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        return m.find();
    }

      下面看一下测试效果

  测试代码:

public static void main(String[] args) {
        String searchStr = "张三";
        String tabPrefix = "user";
        String[] likeFields = {"userID", "userName", "PY"};
        System.out.println("中文不连续检索,不加and前缀,非预编译形式:");
        System.out.println(buildProFuzzySearch(searchStr, tabPrefix, likeFields, false, true, false, false));
        System.out.println("连续检索,不加and前缀,非预编译形式,非开头匹配:");
        System.out.println(buildProFuzzySearch(searchStr, tabPrefix, likeFields, false, false, false, false));
        System.out.println("连续检索,加and前缀,非预编译形式,开头匹配:");
        System.out.println(buildProFuzzySearch(searchStr, tabPrefix, likeFields, true, false, true, false));
        System.out.println("加and前缀,预编译形式:");
        System.out.println(buildProFuzzySearch(searchStr, tabPrefix, likeFields, true, false, true, true));
        System.out.println("中文不连续检索,不加表前缀,加and前缀,非预编译形式:");
        System.out.println(buildProFuzzySearch(searchStr, null, likeFields, true, true, true, false));
    }

    测试结果:

  要说明的是,有些参数会覆盖其它参数的效果,如设置最后一个参数为true,预编译形式,那么开头匹配,连续匹配,中文不连续匹配均失效;如果为中文不连续匹配,且检索字符串中含中文,那么开头匹配,预编译参数失效等。

  有类似需求的可以修改上面的代码以满足自己的实际需要,代码没有什么难的,只是在做一个功能的时候就想把类似可以会用到的情况都考虑一下,方便下次使用,或者下次只要在原有的基础上进行少量的修改,提高开发效率,同时养成一个举一反三,多方面考虑的好习惯。


亲爱的读者:有时间可以点赞评论一下

点赞(0) 打赏

全部评论

还没有评论!
广告位-帮帮忙点下广告