使用以下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。
答案 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;
}