我有一系列字符串,如[" foo"," bar"," baz"]。我试图找到包含这些单词之一的所有记录,例如:
SELECT * from city WHERE (name LIKE '%foo%' OR name LIKE '%bar%' OR name LIKE '%baz%')
。
有时也会出现一个州,因为我需要这样的查询:
SELECT * from city WHERE (name LIKE '%foo%' OR name LIKE '%bar%' OR name LIKE '%baz%') AND stateId = 11
我在这些搜索中使用Hibernate标准,这是我的方法:
public static List<City> findByPartialName(State state, String... names)
{
if (names.length <= 0)
return null;
Criteria cr = session.createCriteria(City.class);
boolean found = false;
Criterion[] conditions = new Criterion[names.length];
List<String> doneWords = new ArrayList<>( names.length );
int i =0;
for (String city : names)
{
city = city.trim();
if (city.isEmpty() || city.length() < 3)
continue;
if ( doneWords.contains(city) )
continue;
found = true;
conditions[i] = Restrictions.like("name", "%" + city + "%");
doneWords.add(city);
i++;
}
if (! found)
return null;
cr.add( Restrictions.or( conditions ) );
if (state != null)
cr.add( Restrictions.eq("state", state) );
try
{
List<City> cities = cr.list();
return cities;
}
catch (ObjectNotFoundException e)
{
return null;
}
}
这是一个非常神秘的问题。如您所见,我使用名为ArrayList
的{{1}}来跟踪已添加的任何字词。因此,如果我传入数组:doneWords
,那么[Nashua, South, Nashua]
只会在Nashua
条件中添加一次,而不是重复。
如果我传入那个确切的数组(OR
),那么我在这一行得到一个空指针异常:
[Nashua, South, Nashua]
但是如果我注释掉这一行:
List<City> cities = cr.list();
然后一切正常(但doneWords.add(city);
在查询中添加两次,即使它只需要添加一次)。
如果我传入一个不包含任何重复单词的数组,例如,如果我只是传入Nashua
,那么即使没有注释掉[South, Nashua]
行,它也能正常工作。
我对此非常困惑。这里发生了什么?
P.S我将doneWords.add(city)
选项设置为true,我可以看到在show_sql
处抛出NullPointerException
时没有执行任何查询。
答案 0 :(得分:1)
问题似乎来自Criterion数组,您的数组大小与收到的名称数量相同,即使它包含空名称,小于3个字符或重复的名称。在这些情况下,数组将包含少于names.length Criterion对象,其余包含引用您的NPE的空引用。您应该使用List并使用toArray()将其传递给Restrictions.or(),而不是Criterion数组。