Spark使用Java通过HiveServer2 JDBC方式跨集群读取Hive数据
1、环境信息准备
jdbc连接url ,通常都是 端口为10000的连接
jdbc用户名
jdbc密码
2、代码实战
public static void main(String[] args) {
SparkConf conf = new SparkConf().setAppName("Spark-Read-Hive-by-Java")
.setMaster("local[*]");
SparkSession sparkSession = SparkSession.builder().config(conf).enableHiveSupport().getOrCreate();
HiveSqlDialect hiveSqlDialect = new HiveSqlDialect();
JdbcDialects.registerDialect(hiveSqlDialect);
Dataset<Row> rowDataset = sparkSession.read()
.format("jdbc")
.option("url", "jdbc:hive2://ip:10000/db_name")
.option("dbtable", "table_name")
.option("user", "username")
.option("password", "passwd")
.option("driver", "org.apache.hive.jdbc.HiveDriver").load().filter("`table_name.ds`='20210112'");
rowDataset.show();
}
在这里需要特别说明下,为什么要加两行如下代码,并且HiveSqlDialect类的实现
HiveSqlDialect hiveSqlDialect = new HiveSqlDialect();
JdbcDialects.registerDialect(hiveSqlDialect);
HiveSqlDialect实现如下:
import org.apache.spark.sql.jdbc.JdbcDialect;
public class HiveSqlDialect extends JdbcDialect {
@Override
public boolean canHandle(String url){
return url.startsWith("jdbc:hive2");
}
@Override
public String quoteIdentifier(String colName) {
return colName.replace("\"","");
}
}
一开始当不加如上重新方法类的时候,一直无法获取到正确的数据,一度以为写的代码,后查看Spark jdbc源码可以看到一个问题,列返回的时候,用的是双引号“” 加列名,所以才会导致一直没有数据返回,所以需要把这个多余的双引号“”去除。
/**
* Quotes the identifier. This is used to put quotes around the identifier in case the column
* name is a reserved keyword, or in case it contains characters that require quotes (e.g. space).
*/
def quoteIdentifier(colName: String): String = {
s""""$colName""""
}
3、后台日志查看
3.1登陆Cloudera Manager找到之前url中ip对应的HiveServer2 Web Ui相对的地址,并打开
3.2能够很明显看到Active Sessions中活跃的连接出现了一个本地IP地址的连接,并且在Open Queries中出现了对应账号的一条SQL查询;
3.3在历史记录中能够很明显的看到两条查询语句,其中一条就是"select * from 表名 where 1=0"; 一条代码很明显的Spark jdbc方式的查询风格的语句,如果看过源码的同学就知道,只要通过Spark jdbc方式访问的方式,必定会在执行sql之前出现一个"select * from 表名 where 1=0" 风格的查询,此语句是为了校验数据库表和获取Schema。
4、结果如下显示成功