当没有任何内容与查询匹配时,为什么会出现NPE异常

时间:2014-03-28 17:00:45

标签: java datanucleus

使用以下datanucleus查询时,如果没有任何内容与查询匹配,则execute方法会抛出NullPointerException。

StringBuilder query = new StringBuilder("select avg(millis) from ");
query.append(clazz.getName());
query.append(String.format(" where name.equals('%s')", name));
query.append(String.format(" && database.equals('%s')", props.get("database")));
query.append(String.format(" && version.equals('%s')", props.get("version")));
Double ave = (Double) pm.newQuery(query.toString()).execute();

NPE如下:

at org.datanucleus.query.evaluator.memory.SetExpression.avg(SetExpression.java:414)
at org.datanucleus.query.evaluator.memory.InMemoryExpressionEvaluator.getValueForInvokeExpression(InMemoryExpressionEvaluator.java:719)
at org.datanucleus.query.evaluator.memory.InMemoryExpressionEvaluator.processInvokeExpression(InMemoryExpressionEvaluator.java:562)
at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compilePrimaryExpression(AbstractExpressionEvaluator.java:200)
...

我在调试器中花了一些时间,我可以看到传递给SetExpression构造函数的集合是空的。这最终导致了SetExpression.avg方法中的NPE。

当集合为空时,'avg'是否正确?如果没有与查询匹配的话,文档对于'avg'返回值的含义是模棱两可的,但我不会期望NPE。

2 个答案:

答案 0 :(得分:0)

经过与@Mike Samuel的长时间讨论后,我想这是一个可能的解决方案:

而不是

Double ave = (Double) pm.newQuery(query.toString()).execute();

Double ave=null;
Object aveObject= pm.newQuery(query.toString()).execute();

if (aveObject!=null){
       ave=(Double)aveObject;
}

根据讨论,错误可能在于您正在使用的库,在这种情况下,这些库会尝试取消空值以将其转换为Double。当然,如果不涉及铸造,情况会更好。因此,如果该方法返回Float(例如):

Double ave=null;
Float aveObject= pm.newQuery(query.toString()).execute();

if (aveObject!=null){
       ave=(Double)aveObject;
}

答案 1 :(得分:0)

我认为这可以被解释为datanucleus-core 3.2.13中的一个错误,假设如果没有选定的记录,avg投影的期望行为将返回0。

他们的SetExpression.avg的实现读取:

if (itemIterator == null)
{
    return 0.0d;
}

我不是100%肯定,但我认为如果将其更改为以下内容,则会以正确的方式解析NPE,如果没有选择记录则返回0

if (itemIterator == null || !iterator.hasNext())
{
    return 0.0d;
}