第十三天 - 封装JDBC操作Hive工具类 - HWI配置与使用 - JavaWeb结合Hive

第十三天 - 封装JDBC操作Hive工具类 - HWI配置与使用 - JavaWeb结合Hive

一、Hive Sql语句补充

通过创建中间表来存储查询出的信息

  • use test;

    show tables;

    1536836805291

    select * from make limit 10;

    1536836827766

    create table t1 as select * from make limit 10;

    1536819857138

    select * from t1;

1536819864785

  • create table t2 as

    select floor(p.age/10) as age,sum(o.retail) as sum

    from orders o left join purchaser p

    on o.puechaserId = p.id

    group by floor(p.age/10);

    1536819885162

    select * from t2;

    1536819894947

二、封装JDBC操作Hive工具类

HiveJDBC操作Hive的基础上封装工具类

HiveUtil.java

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

public class HiveUtil {

    private Statement statement = null;

    public HiveUtil() {
        open();
    }

    static {
        // 1.加载驱动
        try {
            Class.forName("org.apache.hive.jdbc.HiveDriver");
        } catch (ClassNotFoundException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
    }

    private void open() {
        try {
            // 2.打开连接
            Connection connection = DriverManager.getConnection("jdbc:hive2://SZ01:10010/test");
            // 3.获得操作对象
            statement = connection.createStatement();
        } catch (Exception e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
    }
    /**
     * 创建数据库 - 用户注册时调用
     * @param databaseName 根据用户标识生成的数据库名称
     */
    public void createDatabase(String databaseName) {
        try {
            statement.execute("create database " + databaseName);
        } catch (SQLException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
    }
    /**
     * 切换数据库 - 只对当前会话有效
     * @param databaseName 目标数据库名称
     */
    public void changeDatabase(String databaseName) {
        try {
            statement.execute("use " + databaseName);
        } catch (SQLException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
    }
    /**
     * 获得当前数据库中的数据列表 - 注意切换数据库
     * @return 数据表名称的集合
     */
    public List<String> getTableList() {
        List<String> list = new ArrayList<>();
        try {
            ResultSet rs = statement.executeQuery("show tables");
            while(rs.next()) {
                list.add(rs.getString(1));
            }
        } catch (SQLException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        return list;
    }
    /**
     * 获得数据表的简要信息
     * @param tableName 数据表名称
     * @return 列名及列的数据类型
     */
    public List<String> descTable(String tableName){
        List<String> list = new ArrayList<>();
        try {
            ResultSet rs = statement.executeQuery("desc " + tableName);
            while(rs.next()) {
                list.add(rs.getString(1) + "\t" + rs.getString(2));
            }
        } catch (SQLException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        return list;
    }
    /**
     * 获取数据表前十条的预览数据
     * @param tableName 数据表名称
     * @return 数据表预览数据
     */
    public List<String> tableMsg(String tableName){
        int tableSize = descTable(tableName).size();
        List<String> list = new ArrayList<>();
        try {
            ResultSet rs = statement.executeQuery("select * from "+ tableName +" limit 10");
            while(rs.next()) {
                String a = "";
                for(int i = 1; i <= tableSize; i++) {
                    a += rs.getString(i) + "\t";
                }
                list.add(a);
            }
        } catch (SQLException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        return list;
    }
    /**
     * 获得查询sql执行后的返回结果
     * @param sql 用户自定义sql
     * @return sql执行结果集中的所有数据
     */
    public List<String> getResultData(String sql){
        List<String> list = new ArrayList<>();
        // 生成一个对于当前流程唯一的中间表名称
        // 如果流程会反复执行则先删除该表再创建
        String tableName = "data_flow";
        sql = "create table " + tableName + " as " + sql;
        try {
            // 执行查询语句,同时使用一个表进行记录
            statement.execute(sql);
            // 获得中间表的列信息 - 取决于用户执行sql的结果集结构
            int tableSize = descTable(tableName).size();
            ResultSet rs = statement.executeQuery("select * from " + tableName);
            while(rs.next()) {
                String a = "";
                for(int i = 1; i <= tableSize; i++) {
                    a += rs.getString(i) + "\t";
                }
                list.add(a);
            }
        } catch (SQLException e) {
            // TODO 自动生成的 catch 块
            e.printStackTrace();
        }
        return list;
    }
}

HiveUtilTest.java

import java.util.List;

import com.cry.hive.util.HiveUtil;

public class HiveUtilTest {
    public static void main(String[] args) {
        int userId = 1;
        HiveUtil hiveUtil = new HiveUtil();
        // 创建库
        hiveUtil.createDatabase("user" + userId);
        // 切换库
        hiveUtil.changeDatabase("test");
        // 获取当前库中的表列表
        List<String> tables = hiveUtil.getTableList();
        for (String table : tables) {
            System.out.println(table);
            // 获取表结构信息
            List<String> columns = hiveUtil.descTable(table);
            for (String string : columns) {
                System.out.println(string);
            }
            // 获取表内数据信息
            List<String> tableMsg = hiveUtil.tableMsg(table);
            for (String string : tableMsg) {
                System.out.println(string);
            }
            System.out.println();
        }
        // 执行sql语句并获得返回结果
        String sql = "SELECT t.typeName,SUM(o.retail) as sum FROM orders o LEFT JOIN type t ON o.typeId = t.id GROUP BY o.typeId,t.typeName";
        List<String> list = hiveUtil.getResultData(sql);
        for (String line : list) {
            System.out.println(line);
        }
    }
}

三、HiveWebInterface - Hive的Web页面接口

Hive架构图中,CLI和JDBC都已经使用过,还有一种操作Hive的方式WebGUI,即hwi

HWI源码打包配置

hwi依赖hive-hwi-1.2.2.war,但是hive安装包目录的lib目录下没有提供,所以需要下载hive的源码包自行打包。

  1. 从apache官网下载apache-hive-1.2.2-src.tar.gz

  2. 通过Xftp将源码包上传至CentOS

  3. 解压缩

    tar -zxvf apache-hive-1.2.2-src.tar.gz

  4. 进入解压缩出来的文件夹中hwi/web目录下

    cd apache-hive-1.2.2-src/hwi/web

    1536822896066

  5. 使用命令打包web文件夹

    jar cvfM hive-hwi-1.2.2.war -C web .

  6. 将打包完成的war文件移动至hive安装目录的lib目录下

    mv hive-hwi-1.2.2.war $HIVE_HOME/lib

HWI配置

移动完成后,尝试启动hwi服务,此时启动报错,原因是为在hive-site.xml中没有指定hwi目录

hive –service hwi

1536823211313

此时修改配置文件hive-site.xml,添加以下内容

hive.hwi.war.file

​ lib/hive-hwi-1.2.2.war

注:apache官网中建议配置三项,其中两项默认即可,一是主机0.0.0.0,二是端口号9999,第三项hive.hwi.war.file需指定

1536823307212

再次尝试启动服务

hive –service hwi

发现依旧此时报错,原因是hive缺少jsp依赖

1536823402476

此时可以访问9999端口,但是报错

1536823446211

缺少的jar包可通过Maven下载,点击进入

搜索jasper,下载Jasper Runtime和Jasper Compiler

1536823600090

1536823694742

还缺少commons-el的jar包,一起下载即可

1536823832124

还缺少tools.jar,此jar包在jdk的lib中

总共需要的jar包如下图

1536838201277

将这四个jar包通过Xftp上传至CentOS的$HIVE_HOME/lib目录下

重启hwi服务,即可正常使用

Ctrl + c

hive –service hwi

1536823926585

hive –service hwi命令需要停在当前窗口会话,如果ctrl+c或者关闭会话,服务则无法使用,此时执行以下命令

nohup hive –service hwi > /dev/null 2>&1 &

此命令的含义是开启后台进程并且丢弃nohup.out文件

HWI使用
  • 通过Browse Schema可以浏览库中的信息

    1536824025792

  • 通过Create Session创建一个会话,可以执行hql语句

    1536824973429

    1536825058985

    任务完成后,查看结果

    1536825128514

    1536825138476

    也可以在指定的文件中查看结果

    1536825181665

四、JavaWeb结合Hive(一)

注意点
  1. 在Web中操作Hive,需要给每个用户分配独有的空间,否则容易发生冲突,而且会把数据库内弄得杂乱,不好管理

  2. 用户注册,相当于在HDFS创建相应的目录(MapReduce),在Hive中新建相应的库

  3. 数据库的切换有两种方式:

    (1)打开连接时指定数据库

    (2)使用前切换至相应的数据库下

  4. 数据流管理:数据源在经过多次处理后才能得出最终结果,所以在数据库中需专门建立数据库存放在操作过程中生成的中间表,避免数据库中杂乱无章

准备工作
  • 创建Maven项目,注意需要在pom.xml中配置hadoop、hive、json、jstl等依赖配置
  • 创建普通java项目,则需要手动导入hadoop、hive、json、jstl等等依赖包
  • 导入前文编写的工具类HiveUtil.java
  • 导入jquery
编写代码

目标功能:在页面中显示一个按钮,点击后展示数据库中的所有表

datasource.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
    <script type="text/javascript" src="js/jquery-1.7.1.min.js"></script>
    <script type="text/javascript" src="js/datasource.js"></script>
</head>
<body>
    <input class="showTables" type="button" value="显示数据表" />
    <div class="tableList"></div>
    <div class="tableInfo"></div>
    <div class="tableData"></div>
</body>
</html>

datasource.js

$(function() {
    $(".showTables").click(function() {
        var databaseName = "test";
        $.ajax({
            url : "DataSourceServlet",
            type : "post",
            data : {
                databaseName : databaseName
            },
            dataType : "json",
            success : function(data) {
                var content = $(".tableList");
                for (index in data) {
                    var tableName = data[index];
                    content.append("<div><span>"+ tableName +"</span><input type='button' value='预览数据' /><input type='button' value='结构信息' /></div>");
                }
            }
        })
    })
})

DataSourceServlet.java

import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.sand.util.HiveUtil;

import net.sf.json.JSONArray;
@WebServlet("/DataSourceServlet")
public class DataSourceServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    public DataSourceServlet() {
        super();
        // TODO Auto-generated constructor stub
    }

    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        response.setCharacterEncoding("UTF-8");
        PrintWriter out = response.getWriter();
        // 获取数据库名
        String databaseName = request.getParameter("databaseName");
        HiveUtil hiveUtil = new HiveUtil();
        // 通过数据库名切换数据库
        hiveUtil.changeDatabase(databaseName);
        // 获得表集合
        List<String> list = hiveUtil.getTableList();
        for (String line : list) {
            System.out.println(line);
        }
        // 将结果作为json数组传回到页面
        String result = JSONArray.fromObject(list).toString();
        out.print(result);
        out.close();
    }

    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

}
运行结果

1536839283655

1536839364239

待实现功能:点击预览数据能获得表内的前十条数据,点击结构信息能获得表结构信息,并且都是在当前页面展示

猜你喜欢

转载自blog.csdn.net/cry970795248/article/details/82693888