hive-hbase 集成抛出 classnotfoundexception NULL::character 变化
hive-hbase integration throws classnotfoundexception NULL::character varying
我正在尝试集成hive和hbase,我在hive中有这样的配置-site.xml:
<property>
<name>hive.aux.jars.path</name>
<value>
file:///$HIVE_HOME/lib/hive-hbase-handler-2.0.0.jar,
file:///$HIVE_HOME/lib/hive-ant-2.0.0.jar,
file:///$HIVE_HOME/lib/protobuf-java-2.5.0.jar,
file:///$HIVE_HOME/lib/hbase-client-1.1.1.jar,
file:///$HIVE_HOME/lib/hbase-common-1.1.1.jar,
file:///$HIVE_HOME/lib/zookeeper-3.4.6.jar,
file:///$HIVE_HOME/lib/guava-14.0.1.jar
</value>
</property>
然后在hbase中创建一个名为'ts:testTable'的table:
hbase> create 'ts:testTable','pokes'
hbase> put 'ts:testTable', '10000', 'pokes:value','val_10000'
hbase> put 'ts:testTable', '10001', 'pokes:value','val_10001'
...
hbase> scan 'ts:testTable'
ROW COLUMN+CELL
10000 column=pokes:value, timestamp=1462782972084, value=val_10000
10001 column=pokes:value, timestamp=1462783514212, value=val_10001
....
然后在配置单元中创建外部 table:
Hive> CREATE EXTERNAL TABLE hbase_test_table(key int, value string )
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key, pokes:value")
TBLPROPERTIES ("hbase.table.name" = "ts:testTable",
"hbase.mapred.output.outputtable" = "ts:testTable");
到目前为止一切顺利。但是当我尝试 select 来自测试 table 的数据时,抛出了异常:
Hive> select * from hbase_test_table;
FAILED: RuntimeException java.lang.ClassNotFoundException: NULL::character varying
Error: Error while compiling statement: FAILED: RuntimeException java.lang.ClassNotFoundException: NULL::character varying (state=42000,code=40000)
我错过了什么吗?
我正在尝试 Hive 2.0.0 和 HBase 1.2.1
好的,我明白了,"NULL::character varying" 不是配置单元的一部分,它来自 Postgresql,因为我将它用作 Metastore 的后端。但问题是 Hive 无法识别来自 Postgresql 的这个异常。我们有以下 Hive 2.0.0 代码:
300: if (inputFormatClass == null) {
301: try {
302: String className = tTable.getSd().getInputFormat();
303: if (className == null) {
304: if (getStorageHandler() == null) {
305: return null;
306: }
307: inputFormatClass = getStorageHandler().getInputFormatClass();
308: } else {
309: inputFormatClass = (Class<? extends InputFormat>)
310: Class.forName(className, true, Utilities.getSessionSpecifiedClassLoader());
}
第 302 行不会 return null 应该是。这样第310行会尝试加载一个不存在的class。这就是程序失败的原因。
我认为这是一个兼容的错误,修复它的方法是更改我讨厌的数据库。所以我只是简单地将 302 替换为
if (className == null || className.toLowerCase().startsWith("null::")) {
对 getOutputFormat() 方法做同样的事情,然后重新编译 jar,就是这样。
我正在尝试集成hive和hbase,我在hive中有这样的配置-site.xml:
<property>
<name>hive.aux.jars.path</name>
<value>
file:///$HIVE_HOME/lib/hive-hbase-handler-2.0.0.jar,
file:///$HIVE_HOME/lib/hive-ant-2.0.0.jar,
file:///$HIVE_HOME/lib/protobuf-java-2.5.0.jar,
file:///$HIVE_HOME/lib/hbase-client-1.1.1.jar,
file:///$HIVE_HOME/lib/hbase-common-1.1.1.jar,
file:///$HIVE_HOME/lib/zookeeper-3.4.6.jar,
file:///$HIVE_HOME/lib/guava-14.0.1.jar
</value>
</property>
然后在hbase中创建一个名为'ts:testTable'的table:
hbase> create 'ts:testTable','pokes'
hbase> put 'ts:testTable', '10000', 'pokes:value','val_10000'
hbase> put 'ts:testTable', '10001', 'pokes:value','val_10001'
...
hbase> scan 'ts:testTable'
ROW COLUMN+CELL
10000 column=pokes:value, timestamp=1462782972084, value=val_10000
10001 column=pokes:value, timestamp=1462783514212, value=val_10001
....
然后在配置单元中创建外部 table:
Hive> CREATE EXTERNAL TABLE hbase_test_table(key int, value string )
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES ("hbase.columns.mapping" = ":key, pokes:value")
TBLPROPERTIES ("hbase.table.name" = "ts:testTable",
"hbase.mapred.output.outputtable" = "ts:testTable");
到目前为止一切顺利。但是当我尝试 select 来自测试 table 的数据时,抛出了异常:
Hive> select * from hbase_test_table;
FAILED: RuntimeException java.lang.ClassNotFoundException: NULL::character varying
Error: Error while compiling statement: FAILED: RuntimeException java.lang.ClassNotFoundException: NULL::character varying (state=42000,code=40000)
我错过了什么吗?
我正在尝试 Hive 2.0.0 和 HBase 1.2.1
好的,我明白了,"NULL::character varying" 不是配置单元的一部分,它来自 Postgresql,因为我将它用作 Metastore 的后端。但问题是 Hive 无法识别来自 Postgresql 的这个异常。我们有以下 Hive 2.0.0 代码:
300: if (inputFormatClass == null) {
301: try {
302: String className = tTable.getSd().getInputFormat();
303: if (className == null) {
304: if (getStorageHandler() == null) {
305: return null;
306: }
307: inputFormatClass = getStorageHandler().getInputFormatClass();
308: } else {
309: inputFormatClass = (Class<? extends InputFormat>)
310: Class.forName(className, true, Utilities.getSessionSpecifiedClassLoader());
}
第 302 行不会 return null 应该是。这样第310行会尝试加载一个不存在的class。这就是程序失败的原因。
我认为这是一个兼容的错误,修复它的方法是更改我讨厌的数据库。所以我只是简单地将 302 替换为
if (className == null || className.toLowerCase().startsWith("null::")) {
对 getOutputFormat() 方法做同样的事情,然后重新编译 jar,就是这样。