我有一个字符串数组,例如 ["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
叫doneWords
跟踪任何已添加的单词。因此,如果我传入数组: [Nashua, South, Nashua]
,然后Nashua
只会添加到OR
中条件一次,而不是重复。
如果我传入那个确切的数组( [Nashua, South, Nashua]
),那么我会在这一行得到一个空指针异常:
List<City> cities = cr.list();
但是如果我注释掉这一行:
doneWords.add(city);
然后一切正常(但是 Nashua
在查询中添加了两次,即使它只需要添加一次)。
如果我传入一个不包含任何重复单词的数组,例如,如果我只是传入 [South, Nashua]
,那么即使不注释掉 doneWords.add(city)
,它也可以工作。线。
我对此感到非常困惑。这是怎么回事?
P.S我有show_sql
选项设置为 true,我可以看到当 NullPointerException
时没有执行任何查询。被抛出 cr.list()
.
最佳答案
问题似乎来自于 Criterion 数组,即使数组包含空名称、小于 3 个字符的名称或重复名称,您的数组的大小也会根据收到的名称数量进行调整。在这些情况下,数组将包含小于名称的长度 Criterion 对象,其余的包含空引用,这会导致 NPE。您应该使用 List 并使用 toArray() 将其传递给 Restrictions.or(),而不是 Criterion 数组。
关于java - Hibernate criteria.list() 在神秘情况下抛出 NullPointerException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24058908/