Spark JDBC API访问含Map类型列的Hive表时报错如何处理?
报错原因
Hive的map/array/struct等复杂类型通过JDBC协议返回时,会被Hive JDBC驱动标记为JAVA_OBJECT类型,而Spark原生JDBC数据源默认没有适配该类型的解析逻辑,因此抛出类型不支持的异常。
可行解决方案
方案1:查询时转换复杂类型为字符串(推荐JDBC场景使用)
在JDBC查询语句中先把map类型列序列化为JSON字符串,读取到Spark后再反序列化为map类型,改动成本极低,兼容性好。
代码示例:// 读取时用Hive的to_json函数把map转成JSON字符串 val tempdf= spark.read.format("jdbc") .option("driver", "org.apache.hive.jdbc.HiveDriver") .option("url", "jdbc:hive2://localhost:10000/tempdb") .option("user","user1") .option("password","password1") .option("query","select statementid, batchid, to_json(requestparam) as requestparam_json from tempdb.tableA") .load() // 把JSON字符串转回Spark的Map类型 import org.apache.spark.sql.functions.{col, from_json} import org.apache.spark.sql.types.{MapType, StringType} val resultDf = tempdf.withColumn("requestparam", from_json(col("requestparam_json"), MapType(StringType, StringType))) .drop("requestparam_json")若使用的Hive版本不支持
to_json函数,也可以通过lateral view explode拼接KV字符串,再用Spark的str_to_map函数转回map类型。方案2:直接用Spark原生Hive能力读取(同集群场景最优)
如果你的Spark环境已经配置了Hive连接(将hive-site.xml放入Spark的conf目录或项目资源目录),可以跳过JDBC,直接用Spark原生的Hive元数据能力读取,原生支持所有Hive复杂类型,性能也远高于JDBC读取。
代码示例:val tempdf = spark.table("tempdb.tableA")方案3:自定义Spark JDBC类型映射(不推荐)
你也可以通过自定义Spark JDBC方言、重写
JAVA_OBJECT类型的解析逻辑适配Hive复杂类型,但是改动成本高,需要对Spark JDBC模块的源码有一定了解,非必要场景不建议使用。
内容的提问来源于stack exchange,提问作者Narendra Rokade
相关产品推荐
相关产品推荐

