Spark使用Java通过HiveServer2 JDBC方式跨集群读取Hive数据

9 篇文章 0 订阅
6 篇文章 0 订阅

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、结果如下显示成功

好的,我了解了您的问题。下面是具体的步骤: 1. 首先需要在Spark的classpath中添加相关的Jar包: ``` spark-shell --master yarn --jars /path/to/hive-jdbc.jar,/path/to/hbase-client.jar,/path/to/hbase-common.jar,/path/to/hbase-server.jar,/path/to/hive-exec.jar,/path/to/hive-metastore.jar ``` 这里的Jar包路径需要根据您的实际情况进行修改。 2. 接下来需要创建HiveContext,然后使用HiveContext读取Hive表中的数据: ```scala val hiveContext = new HiveContext(sc) val df = hiveContext.sql("select * from mytable") ``` 这里的mytable是您需要上传到HBase的Hive表名,可以根据实际情况进行修改。 3. 创建HBase的连接和表: ```scala val hbaseConf = HBaseConfiguration.create() hbaseConf.set("hbase.zookeeper.quorum", "your.zookeeper.quorum") val tableName = TableName.valueOf("mytable") val hBaseConn = ConnectionFactory.createConnection(hbaseConf) val hBaseTable = hBaseConn.getTable(tableName) ``` 其中,hbase.zookeeper.quorum需要设置为您的Zookeeper集群的地址,mytable是您需要在HBase中创建的表名。 4. 将Hive表中的数据上传到HBase: ```scala df.foreachPartition { partition => val hBasePuts = new util.ArrayList[Put]() partition.foreach { row => val put = new Put(Bytes.toBytes(row.getString(0))) // 这里假设第一列是RowKey // 依次将每个列族的每个列添加到Put中 put.addColumn(Bytes.toBytes("cf1"), Bytes.toBytes("col1"), Bytes.toBytes(row.getString(1))) put.addColumn(Bytes.toBytes("cf1"), Bytes.toBytes("col2"), Bytes.toBytes(row.getString(2))) hBasePuts.add(put) } hBaseTable.put(hBasePuts) } ``` 这里将每个Hive表中的行转换为HBase中的Put,并将这些Put添加到一个List中,最后一次性将这个List中的所有Put上传到HBase。 5. 最后不要忘记关闭HBase的连接: ```scala hBaseTable.close() hBaseConn.close() ``` 以上就是用Spark连接Hive并将数据上传到HBase的具体步骤。希望能帮到您!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值