0xTTEPX

Just do it, deeply...

Follow me on GitHub

HIVE客户端简单API

write by donaldhan, 2020-03-05 23:11

引言

我们先来回顾一下上一篇HIVE DDL&DML简介所讲内容。 如果创建数据库时没有指定对应的数仓存储路径,默认为HDFS下的数仓目录user/hive/warehouse+数据库名+.db对应的文件夹。 如果数据库中有0或多个表时,不能直接删除,需要先删除表再删除数据库;如果想要删除含有表的数据库,在删除时加上cascade,可以级联删除(慎用)。 Hive表有两种,分别是内部表与外部表,如果是内部表,在删除时,MySQL中的元数据和HDFS中的数据都会被删除; 如果是外部表,在删除时,MySQL中的元数据会被删除,HDFS中的数据不会被删除; 加载文件数据到Hive表有两种方式,一种是从本地文件加载,一种从hdfs文件加载。如果加上LOCAL表示从本地加载数据, 默认不加,从hdfs中加载数据,添加OVERWRITE关键字,将会覆盖表中数据,及先删除,在加载。 从hdfs方式加载完数据,需要注意hdfs上的文件将会被删除,移动hdfs的垃圾箱中。 插入数据实际为一个MR任务。聚合类的操作(max,min,avg,count),都需要运行MR任务。 导出数据与加载数据LOCAL和OVERWRITE使用基本一致。如果加上LOCAL表示导出到本地默认不加,导出到hdfs,如果加OVERWRITE关键字,将会覆盖原文件中的数据,及先删除,在导出。 从本地加载文件到分区表时,实际上是,将本地文件放到hdfs上的数据库分区表文件夹(order_partition)下的分区字段+分区Value(event_month=2020-02)文价夹。 单级分区和多级分区唯一的区别就是多级分区在hdfs中的目录为多级。

今天我们来看一下client api的使用。

目录

从搜索的结果来看,hive client API相关的文章,在大数据的场景中,应该没有这种java直接访问hive,要结合spark、今天我们只做一个简单的测试。 HIVE环境我们使用的是单机版的,具体参考下文:

HIVE单机环境搭建:https://donaldhan.github.io/bigdata/2020/02/25/HIVE%E5%8D%95%E6%9C%BA%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA.html

添加依赖

<dependency>
    <groupId>org.apache.hive</groupId>
    <artifactId>hive-jdbc</artifactId>
    <version>2.1.0</version>
    <exclusions>
        <exclusion>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
        </exclusion>
    </exclusions>
</dependency>

测试DEMO

具体测试代码如下

package com.hive.jdbc.client;



import groovy.util.logging.Slf4j;
import org.mortbay.log.Log;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
/**
 * @author revanthreddy
 * 使用前,启动hiveserver2
 */
@Slf4j
public class HiveJdbcClient {
	private static final String DRIVER_NAME = "org.apache.hive.jdbc.HiveDriver";

	public static void main(String[] args) throws SQLException {
		try {
			Class.forName(DRIVER_NAME);
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
			System.exit(1);
		}
		Connection con = DriverManager.getConnection("jdbc:hive2://pseduoDisHadoop:10000/test", "hadoop", "123456");
		Statement stmt = con.createStatement();

		String tableName = "student";
		stmt.execute("DROP TABLE " + tableName);
		String query = "CREATE TABLE student (id int,name string,tel string,age int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t'";

		stmt.execute(query);

		// show tables
		String sql = "show tables";
		Log.info("Running Query : {}" ,sql);
		ResultSet res1 = stmt.executeQuery(sql);
		if (res1.next()) {
			System.out.println(res1.getString(1));
		}

		// describe table
		sql = "describe " + tableName;
		Log.info("Running Query : {}" + sql);
		res1 = stmt.executeQuery(sql);
		while (res1.next()) {
			System.out.println(res1.getString(1) + "\t" + res1.getString(2));
		}

		// load data into table , 这里使用的是本地文件加载数据方式
		String filepath = "/bdp/hive/hiveLocalTables/student.txt";
		sql = "load data local inpath '" + filepath + "' into table " + tableName;
		Log.info("Running Query :{} " ,sql);
		stmt.execute(sql);

		// select * query
		String sqlquery = "select * from " + tableName;
		Log.info("Running Query :{} " ,sqlquery);
		ResultSet res2 = stmt.executeQuery(sqlquery);
		while (res2.next()) {
			Log.info(String.valueOf(res2.getInt(1)) + "\t" + res2.getString(2));
		}

	}
}

在测试前,要先启动HiveServer2, 应为我们使用的JDBC方式连接HIVE。

注意我们的LOG使用的是import groovy.util.logging.Slf4j; 而不是LOMBOK。

本文中的代码可以从下面的仓库中拉去。

HiveMetaStoreClient:https://github.com/Donaldhan/HiveMetaStoreClient

引用文献

使用hive客户端java api读写hive集群上的信息:https://www.bbsmax.com/A/1O5EBAy7d7/
hdinsight-java-hive-jdbc:https://github.com/Azure-Samples/hdinsight-java-hive-jdbc
HiveMetaStoreClient:https://github.com/Re1tReddy/HiveMetaStoreClient

org.apache.thrift.server.TThreadPoolServer$WorkerProcess.run(TThreadPoolServer.java:286)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: org.apache.hadoop.hive.ql.parse.ParseException:line 1:108 cannot recognize input near ';' '<EOF>' '<EOF>' in serde properties specification
	at org.apache.hadoop.hive.ql.parse.ParseDriver.parse(ParseDriver.java:211)
	at org.apache.hadoop.hive.ql.parse.ParseUtils.parse(ParseUtils.java:77)
	at org.apache.hadoop.hive.ql.parse.ParseUtils.parse(ParseUtils.java:70)
	at org.apache.hadoop.hive.ql.Driver.compile(Driver.java:468)
	at org.apache.hadoop.hive.ql.Driver.compileInternal(Driver.java:1317)
	at org.apache.hadoop.hive.ql.Driver.compileAndRespond(Driver.java:1295)
	at org.apache.hive.service.cli.operation.SQLOperation.prepare(SQLOperation.java:204)
	... 15 more
Disconnected from the target VM, address: '127.0.0.1:54934', transport: 'socket'

Process finished with exit code 1

这个是由于我的SQL语句多一个的一个分号;

String query = "CREATE TABLE student (id int,name string,tel string,age int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t';";
String query = "CREATE TABLE student (id int,name string,tel string,age int) ROW FORMAT DELIMITED FIELDS TERMINATED BY '\\t'";

ERROR StatusLogger No log4j2 configuration file found

原因,log4j2只支持xml和json两种格式的配置,所以配置log4j.properties是没有作用的。要把log4j.properties的文件改为log4j2.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
        </Console>

        <RollingFile name="RollingFile" filename="log/hiveMetaStore.log"
                     filepattern="%d{yyyy-MM-dd}.log">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n" />
            <Policies>
                <SizeBasedTriggeringPolicy size="10 MB" />
            </Policies>
            <DefaultRolloverStrategy max="20" />
        </RollingFile>

    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="Console" />
            <AppenderRef ref="RollingFile" />
        </Root>
    </Loggers>
</Configuration>