作者:whisper
链接:http://proprogrammar.com:443/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,预编译形式,那么开头匹配,连续匹配,中文不连续匹配均失效;如果为中文不连续匹配,且检索字符串中含中文,那么开头匹配,预编译参数失效等。
有类似需求的可以修改上面的代码以满足自己的实际需要,代码没有什么难的,只是在做一个功能的时候就想把类似可以会用到的情况都考虑一下,方便下次使用,或者下次只要在原有的基础上进行少量的修改,提高开发效率,同时养成一个举一反三,多方面考虑的好习惯。
亲爱的读者:有时间可以点赞评论一下
全部评论