如何让HiveWarehouseSessionImpl适配Spark本地会话开展单元测试?
问题:HiveWarehouseSessionImpl适配Spark本地单元测试的方案
我之前基于Spark本地会话编写单元测试,代码如下:
SparkSession spark = TestHiveSparkSession.builder().master("local").enableHiveSupport().getOrCreate();
执行SQL用的是:
spark.sql("select * from blabla");
升级Hadoop版本后,原有方式不再适用,需要迁移至HiveWarehouseSessionImpl。通常生成会话的方式是:
HiveWarehouseSessionImpl impl = HiveWarehouseSession.session(spark).build();
或者:
HiveWarehouseSessionImpl impl = HiveWarehouseBuilder.session(spark).build();
但执行时抛出错误:
NoSuchElement spark.sql.hive.hiveserver2.jdbc.url
配置URL后,又提示缺少对应驱动;添加驱动后,因为未启动Hive Server,无法建立连接。
请问能否让HiveWarehouseSessionImpl像之前一样适配本地会话,还是必须重构代码?我希望通过这个新的Spark+Hive封装方案,沿用原有方式执行单元测试中的SQL。
版本信息:
- 新环境:spark-core_2.11 2.4.7.7.1.7.2000-305,Hadoop 3.1.1.7.1.7.2000-305
- 旧环境:spark-core_2.11 2.4.0-cdh6.3.4,Hadoop 3.0.0-cdh6.3.4
解决方案
1. 无需强制重构,可通过配置适配本地模式
HiveWarehouseSession默认依赖HiveServer2的JDBC连接,但可以通过配置强制它使用Spark本地的Hive元数据和执行引擎,绕过HS2:
在构建SparkSession时添加以下关键配置:
SparkSession spark = TestHiveSparkSession.builder() .master("local") .enableHiveSupport() .config("spark.sql.hive.hiveserver2.jdbc.url", "jdbc:hive2://localhost:10000") // 仅作为占位配置,本地模式不会实际建立连接 .config("spark.sql.hive.hiveserver2.jdbc.driver", "org.apache.hive.jdbc.HiveDriver") .config("hive.metastore.uris", "") // 禁用远程元存储,使用本地内嵌元存储 .config("spark.sql.hive.hivewarehousesession.mode", "spark") // 核心配置:切换为Spark执行模式 .getOrCreate();
之后构建HiveWarehouseSessionImpl即可复用Spark本地Hive上下文,无需启动HS2:
HiveWarehouseSessionImpl impl = HiveWarehouseSession.session(spark).build(); // 沿用类似原有方式执行SQL impl.executeQuery("select * from blabla");
2. 解决驱动缺失问题
如果仍提示驱动缺失,确保测试依赖中包含对应版本的Hive JDBC驱动(以Maven为例):
<dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-jdbc</artifactId> <version>对应你的Hive版本</version> <scope>test</scope> </dependency>
3. 备选:封装统一执行层兼容新旧模式
如果需要后续兼容两种执行方式,可以封装工具类自动适配:
public class SqlExecutor { private final SparkSession spark; private HiveWarehouseSessionImpl hiveWarehouseSession; public SqlExecutor(SparkSession spark) { this.spark = spark; try { this.hiveWarehouseSession = HiveWarehouseSession.session(spark).build(); } catch (Exception e) { // 适配失败时 fallback 到原生spark.sql this.hiveWarehouseSession = null; } } public Dataset<Row> execute(String sql) { return hiveWarehouseSession != null ? hiveWarehouseSession.executeQuery(sql) : spark.sql(sql); } }
单元测试调用时只需使用sqlExecutor.execute(sql),无需修改原有业务逻辑。
内容的提问来源于stack exchange,提问作者Ebenezer Ingeliakastimiziliani
相关产品推荐
相关产品推荐

