Play框架使用Anorm连接Spark Thrift Server JDBC失败求助
解决Anorm连接Spark Thrift Server时SQLFeatureNotSupportedException异常
环境信息
- Play框架:2.8.18
- Anorm:2.7.0
- Spark Thrift Server:Spark 3.2.1 + Hadoop 3.2
- Scala:2.13.5
- JDBC驱动:hive-jdbc 3.1.3
问题现象
通过Play框架的Anorm连接Spark Thrift Server时抛出异常,关键栈信息如下:
java.sql.SQLFeatureNotSupportedException: Method not supported at org.apache.hive.jdbc.HiveResultSetMetaData.getTableName(HiveResultSetMetaData.java:102) at anorm.MetaData$.tableName$1(MetaData.scala:148) ...(省略后续栈信息)
排查情况
- 已用纯Java代码验证,相同的hive-jdbc 3.1.3驱动可正常连接并执行查询,说明驱动本身能正常交互,问题出在Anorm的调用逻辑上:
package org.example; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class HiveJDBCConnect { public static void main(String[] args) { Connection con = null; try { String conStr = "jdbc:hive2://spark-thrift:10000/test_schema;auth=noSasl"; Class.forName("org.apache.hive.jdbc.HiveDriver"); con = DriverManager.getConnection(conStr, "root", "root"); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery("select key2 from ir_test"); while(rs.next()) { System.out.print(rs.getString(1)); System.out.println(); } System.out.println("show database successfully."); } catch (Exception ex) { ex.printStackTrace(); } finally { try { if (con != null) con.close(); } catch (Exception ex) { } } }}
- 尝试过
spark-project-hive-jdbc 1.2.1.spark驱动,但因连接池问题无法建立连接。
解决方案
方案1:绕过Anorm的元数据自动解析
Anorm部分API会自动解析结果集元数据(调用getTableName)用于表结构映射,这是触发异常的核心原因。可以改用手动字段映射的方式,避免触发元数据解析:
import anorm._ // 不使用依赖元数据的自动映射API,手动提取字段 val query = SQL("select key2 from ir_test") val result: List[String] = query().map(row => row[String]("key2")).toList
方案2:使用Spark官方兼容驱动
换用Spark 3.2.1版本对应的官方Thrift Server驱动,该驱动实现了完整的JDBC元数据方法:
- Maven依赖:
<dependency> <groupId>org.apache.spark</groupId> <artifactId>spark-hive-thriftserver_2.13</artifactId> <version>3.2.1</version> </dependency>
- SBT依赖:
libraryDependencies += "org.apache.spark" % "spark-hive-thriftserver_2.13" % "3.2.1"
注意需排除项目中冲突的hive-jdbc依赖,避免版本冲突。
方案3:临时修改驱动实现(不推荐生产环境)
如果无法更换驱动,可通过字节码增强或自定义HiveResultSetMetaData子类,重写getTableName方法返回空字符串或固定值,替换驱动中的对应类。但这种方式维护成本高,仅作为临时应急方案。
补充说明
纯Java代码能正常运行,是因为直接操作ResultSet时没有触发Anorm中依赖getTableName的元数据解析逻辑,而Anorm的自动映射API会主动调用该方法,才导致了异常。
内容的提问来源于stack exchange,提问作者Bill Goldberg
相关产品推荐
相关产品推荐

