我有以下查询,该查询应该找到列值的平均值,并返回结果,这是一个数字。
val avgVal = hiveContext.sql("select round(avg(amount), 4) from users.payment where dt between '2018-05-09' and '2018-05-09'").first().getDouble(0)
我在这个声明中面对不一致的行为。这通常会失败并出现以下错误,但是当通过Hive执行时它会产生非NULL结果。"
18/05/10 11:01:12 ERROR ApplicationMaster: User class threw exception: java.lang.NullPointerException: Value at index 0 in null
java.lang.NullPointerException: Value at index 0 in null
at org.apache.spark.sql.Row$class.getAnyValAs(Row.scala:475)
at org.apache.spark.sql.Row$class.getDouble(Row.scala:243)
at org.apache.spark.sql.catalyst.expressions.GenericRow.getDouble(rows.scala:192)
我使用HiveContext而不是SQLContext的原因是后者不支持我在代码中广泛使用的一些聚合函数。
您能否帮我理解为什么会出现这个问题以及如何解决?
答案 0 :(得分:1)
您需要划分查询并分为两部分:
var result = hiveContext.sql("select round(avg(amount), 4) from users.payment where dt between '2018-05-09' and '2018-05-09'");
var first = result.first();
if (first != null && !first.isNullAt(0)) {
var avgVal = first.getDouble(0);
}
这样可以避免NPE。在List和数组中也需要这样。
对于插入或更新查询,您甚至需要用try...catch
块来包围以捕获运行时异常。
答案 1 :(得分:0)
让我们分析可以抛出此异常的情况和可能的原因。
Row row = hiveContext.sql("select info, name, desc, id from users.payment where dt between '2018-05-09' and '2018-05-09'").first();
如果上面row
的值返回的内容如下:
[null, Kevin, cash, 300]
尝试获取getDouble(0)
会导致java.lang.NullPointerException: Value at index 0 in null
您可以尝试以下方法:
Row row = hiveContext.sql("select round(avg(amount), 4) from users.payment where dt between '2018-05-09' and '2018-05-09'").first();
if (!row.isNullAt(0))
double d = row.getDouble(0);
else
logger.error("Value at index zero is null");
如果您要检查源代码,那么库类就相反了:
private static Object getAnyValAs(Row $this, int i) {
if($this.isNullAt(i)) {
throw new NullPointerException((new StringContext(scala.Predef..MODULE$.wrapRefArray((Object[])(new String[]{"Value at index ", " is null"})))).s(scala.Predef..MODULE$.genericWrapArray(new Object[]{BoxesRunTime.boxToInteger(i)})));
} else {
return $this.getAs(i);
}
}