第十四天 - JavaWeb结合Hive - Hive外部表 - Hive内置函数 - Hive自定义函数
第十四天 - JavaWeb结合Hive - Hive外部表 - Hive内置函数 - Hive自定义函数
- 第十四天 - JavaWeb结合Hive - Hive外部表 - Hive内置函数 - Hive自定义函数
-
- 一、JavaWeb结合Hive(二)
-
- 完善(一)中的功能
- 创建表、导入数据
-
- 二、Hive外部表
- 三、Hive函数操作
-
- 关系运算
- 数学运算
- 逻辑运算
- 数值运算
- 日期函数
- 字符串函数
-
- 四、Hive自定义函数
-
- 准备工作
- 编写代码
- 打包上传
- 运行测试
- 其他事项
-
- 一、JavaWeb结合Hive(二)
-
一、JavaWeb结合Hive(二)
完善(一)中的功能
JavaWeb结合Hive(一)
实现功能:点击预览数据能获得表内的前十条数据,点击结构信息能获得表结构信息,并且都是在当前页面展示
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("" + tableName + "");}}}) }) // 对于动态添加的元素绑定事件 - on方式实现需要在jQuery的1.7版本以后,live,bind // $(父级选择器).on(事件名称,需要绑定事件的元素-即动态添加进来的元素,方法体-触发事件后执行的内容) // 如果动态添加的元素没有父级元素可以使用document或者body // 此时$(this)依然代表触发事件的元素 $(document).on("click",".info",function(){// 通过data("xxx")方法可以获得当前元素通过data-xxx属性定义的值var tableName = $(this).data("name");// 通过触发事件元素与需要获取信息的元素之间的层级关系进行查找// siblings能够获取到同级元素的集合,也可以直接传入选择器作为参数,如siblings(".className"),会返回同级中匹配的元素//alert($(this).siblings().eq(0).html());$.ajax({url : "TableInfoServlet",type : "post",data : {tableName : tableName},dataType : "json",success:function(data){var content = $(".tableInfo");// 保证指定区域只显示当前表信息,添加信息前先清空content.html("");for(index in data){content.append("" + data[index] + "")}}}) }) $(document).on("click",".data",function(){var tableName = $(this).data("name");$.ajax({url : "TableDataServlet",type : "post",data : {tableName : tableName},dataType : "json",success:function(data){var content = $(".tableData");// 保证指定区域只显示当前表信息,添加信息前先清空content.html("");for(index in data){content.append("" + data[index] + "")}}}) }) })TableInfoServlet.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;/** * Servlet implementation class TableInfoServlet */ @WebServlet("/TableInfoServlet") public class TableInfoServlet extends HttpServlet { private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public TableInfoServlet() {super();// TODO Auto-generated constructor stub}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)*/ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setCharacterEncoding("UTF-8");PrintWriter out = response.getWriter();String tableName = request.getParameter("tableName");HiveUtil hiveUtil = new HiveUtil();hiveUtil.changeDatabase("test");// 当需要获取表信息时,如果只传入表名称会在当前数据库中搜索该表,需要先切换数据库// 如果传入库名.表名 -> 在指定的数据库下进行搜索Listlist = hiveUtil.getTableInfo(tableName);out.print(JSONArray.fromObject(list).toString());out.close(); }/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)*/ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {doGet(request, response); }} TableDataServlet.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;/** * Servlet implementation class TableDataServlet */ @WebServlet("/TableDataServlet") public class TableDataServlet extends HttpServlet { private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public TableDataServlet() {super();// TODO Auto-generated constructor stub}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)*/ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {response.setCharacterEncoding("UTF-8");PrintWriter out = response.getWriter();String tableName = request.getParameter("tableName");HiveUtil hiveUtil = new HiveUtil();hiveUtil.changeDatabase("test");// 当需要获取表信息时,如果只传入表名称会在当前数据库中搜索该表,需要先切换数据库// 如果传入库名.表名 -> 在指定的数据库下进行搜索Listlist = hiveUtil.getTableData(tableName);out.print(JSONArray.fromObject(list).toString());out.close(); }/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)*/ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {// TODO Auto-generated method stubdoGet(request, response); }} 运行效果

创建表、导入数据
load.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title heretitle>
<script type="text/javascript" src="js/jquery-1.7.1.min.js">script>
<script type="text/javascript" src="js/load.js">script>
head>
<body><form action="LoadDataServlet" method="post"enctype="multipart/form-data"><span>数据表名称:span><input type="text" name="tableName" /><br /><label><input type="checkbox" name="auto" value="auto" />从首行中读取字段信息label><br /><label><input type="checkbox" name="overwrite" value="overwrite" />是否覆盖导入label><br /><span>列分隔符:span><input type="text" name="format" /><br /><input type="button" value="添加" class="add" /><div class="columnInfo">div><input type="file" name="data" /> <input type="submit" value="上传" />form><div class="column" style="display: none"><span class="columnNameLabel">列名:span><input type="text" name="columnName" /> <span>数据类型:span><select name="columnType"><option value="int">intoption><option value="string">Stringoption>select> <span class="delete">-span>div>
body>
html>
load.js
$(function(){$(".add").click(function(){var column = $(".column").html();$(".columnInfo").append("" + column + "
");})$(document).on("click",".delete",function(){$(this).parent().remove();})$("input[name='auto']").click(function(){if($(this).attr("checked") == "checked"){$(".columnNameLabel").hide();$("input[name='columnName']").hide();}else{$(".columnNameLabel").show();$("input[name='columnName']").show();}})$("input[type='checkbox']").removeAttr("checked");
})
LoadDataServlet.java
此Servlet功能仅实现了拼接字符串,真正执行的代码待完善
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.util.UUID;import javax.servlet.ServletException;
import javax.servlet.annotation.MultipartConfig;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.Part;/*** Servlet implementation class LoadDataServlet*/
@WebServlet("/LoadDataServlet")
@MultipartConfig
public class LoadDataServlet extends HttpServlet {private static final long serialVersionUID = 1L;/*** @see HttpServlet#HttpServlet()*/public LoadDataServlet() {super();// TODO Auto-generated constructor stub}/*** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse* response)*/protected void doGet(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {// 设置编码request.setCharacterEncoding("UTF-8");response.setCharacterEncoding("UTF-8");response.setContentType("text/plain; charset=UTF-8");// 接收参数String tableName = request.getParameter("tableName");boolean isAuto = request.getParameter("auto") == null ? false : true;boolean isOverwrite = request.getParameter("overwrite") == null ? false : true;String format = request.getParameter("format");if (!isAuto) {String[] columnNames = request.getParameterValues("columnName");}String[] columnTypes = request.getParameterValues("columnType");for (String columnType : columnTypes) {System.out.println(columnType);}// 使用Part对象接收文件Part part = request.getPart("data");// 取出文件名(如果需要)String path = "/tmp";// 可以使用自定义的名称,也可以使用UUIDString fileName = UUID.randomUUID().toString();// 从登陆信息中获取当前用户的唯一标识String userId = "1";String filePath = path + File.separator + fileName;// 使用write方法向路径中写入文件part.write(filePath);Reader reader = new FileReader(new File(filePath));BufferedReader bf = new BufferedReader(reader);String tableInfo = bf.readLine();String createTable = "create table " + tableName + "(";for(int i = 0;i < columnTypes.length;i ++) {createTable += tableInfo.split(format)[i] + " " + columnTypes[i] + ",";}createTable = createTable.substring(0,createTable.length() - 1);createTable += ") row format delimited fields terminated by '" + format + "' tblproperties(\"skip.header.line.count\"=\"1\")";bf.close();reader.close();System.out.println(createTable);String loadToHive = "load data local inpath '"+ filePath +"' " + (isOverwrite ? "overwrite " : "") +"into table " + tableName;System.out.println(loadToHive);}/*** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse* response)*/protected void doPost(HttpServletRequest request, HttpServletResponse response)throws ServletException, IOException {doGet(request, response);}}
将项目打包成war文件,并且用Xftp上传至CentOS中apache安装目录下的webapps目录下

su root切换至root用户,执行./startup.sh启动apache服务,启动后会自动解压war包并部署项目

启动后就可以通过浏览器访问http://sz01/WebProject/load.jsp
待完善
二、Hive外部表
内部表和外部表区别:内部表即完全交给hive管理表,在创建时会将数据移动到数据仓库所
在的路径,删除时会删除数据源文件。外部表即增加hive管理的数据文件,创建时需要记录
数据所在的路径,不会移动数据源文件,删除时不会删除数据源文件
创建外部表
创建时需要用location关键字指定数据所在的路径
create table {tableName}(
{columnName} {columnType},
{columnName} {columnType},
…
)[row format delimited fields terminated by ‘\t’]
[location ‘{HDFS_path}’];
如果指定的文件夹下已经有数据文件,则只要结构匹配就可以直接使用
导入数据即将数据导放置在创建表时指定的目录下
删除外部表,只会删除结构,文件将会保留


注:在mysql创建的hive库中有两张数据元表,其中SDS用于记录表结构对应的路径信息,TBLS用于记录表的基本信息(所属的数据库,数据表类型)
三、Hive函数操作
函数的执行,通过select关键字进行调用;函数之间可以相互嵌套使用,只需要一个select关键字。
根据函数的作用,传入的参数可以是某个固定的值,也可以指表中某个列的字段名称;
传入单个数据时,返回单个的结果,和表产生关联时,返回的是逐条数据调用后返回的结果。
查看可用函数列表
show functions;
查看函数描述信息
desc function {functionName};
关系运算
等值比较
select num1=num2;

不等值比较
select num1>num2;
select num1
数学运算
四则运算
select 6+3;
select 6-3;
select 6*3;
select 6/3;


取余运算
select 25%3;

按位运算
与:select 6&9; 0110&1001=0000
或:select 6|9; 0110|1001=1111
异或:select 6^9; 0110^1001=1111

取反:select ~4;

逻辑运算
如果结果为真,则返回TRUE,否则返回FALSE
逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)

数值运算
取整函数
四舍五入法round:1~4舍,5~9进,传入两个参数时可指定精度
select round (5.369,2);

银行家舍入法bround:1~4舍,6~9进,5->前一位是偶数则舍,前一位是奇数则进,传入两个参数时可指定精度
select bround(5.365,2);
向下取整函数
select floor (5.9);

向上取整函数
select ceil/ceiling (6.1);

生成随机数
rand ([{seed}]):返回一个0到1范围内的随机数,传入参数时可生成稳定的随机数
select rand;

自然指数函数
自然指数e的n次方:exp ({n})
对数函数
- 以10为底的对数函数:log10 ({value})
- 以2为底的对数函数:log2 ({value})
- 以e为底的对数函数:ln ({value})
- 对数函数:log ({base},{value})
幂函数
pow/power ({base},{exponent})
平方根函数
sqrt ({value})
立方根函数
cbrt ({value})
进制函数
- 转二进制函数:bin ({value})
- 转十六进制函数:hex ({value})
- 反转十六进制函数:unhex ({value})
- 进制转换函数:conv ({value},{fromBase},{toBase})
绝对值函数
abs ({value})
日期函数
获取日期函数
unix_timestamp()
时间戳转换函数,在进行日期转换时,可以自定义日期格式
UNIX时间戳转日期:from_unixtime ({unixTime}[,{formatString}])
日期转UNIX时间戳:unix_timestamp ({timeString}[,{formatString}])日期截取函数,使用日期截取函数时,必须针对字符串日期操作
- 返回日期部分:to_date ({timeString})
- 返回日期的年:year ({timeString})
- 返回日期的月:month ({timeString})
- 返回日期的天:day ({timeString})
- 返回日期的时:hour ({timeString})
- 返回日期的分:minute ({timeString})
- 返回日期的秒:second ({timeString})
- 返回日期的周:weekofyear ({timeString})
日期计算函数
- 日期比较函数:datediff ({endDate},{startDate})
- 日期增加函数:date_add ({startData},{days})
- 日期减少函数:date_sub ({startData},{days})
字符串函数
字符串长度函数
length ({stringValue})
字符串翻转函数
reverse ({stringValue})
字符串连接函数
- 无分隔符连接函数:concat ({stringValues})
- 分隔符连接函数:concat_ws ({separator},{stringValues})
字符串截取函数
substr/substring ({stringValue},{index}):当index为正数时,截取从index至结尾的字符串,当index为负数时,截取后index个字符,index的值不能超过字符串长度
substr/substring ({stringValue},{index},{length}):截取从index开始,长度为length的字符,index为正数时,索引从左边开始,index为负数时,索引从右边开始
大小写转换函数
- 转大写函数:upper/ucase ({stringValue})
- 转小写函数:lower/lcase ({stringValue})
去空格函数
- 两边去空格函数:trim ({stringValue})
- 左边去空格函数:ltrim ({stringValue})
- 右边去空格函数:rtrim ({stringValue})
正则表达式函数
正则替换函数:regexp_replace ({stringValue},{regexpString},{replaceValue})
正则解析函数:regexp_extract ({stringValue},{regexpString},{index})URL解析函数(重要)
parse_url ({stringValue},’{extractPart}’)[,’{extractKey}’])
HOST:获取主机名(域名)
PATH:获取访问路径
QUERY:参数解析,需要配合extractKey一起使用
REF:获取锚点信息
PROTOCOL:获取网络协议
FILE:获取路径及参数信息
select parse_url (‘https://www.baidu.com/s?keyword=111‘,’HOST’);

select parse_url (‘https://www.baidu.com/s?keyword=111‘,’QUERY’,’keyword’);

JSON解析函数(重要)
json解析地址
get_json_object({jsonString},’$.{jsonObjectKey}’)
select get_json_object(‘{“name”:”cry”,”age”:20}’,’$.name’);

字符串生成函数
- 空格字符串函数:space (n)
- 重复字符串函数:repeat ({stringValue},n)
首字符ASCII码函数
ascii ({stringValue})
字符串补足函数
将原字符串用指定的追加字符串补足为指定长度的字符串
- 左补足函数:lpad ({stringValue},{length},{appendValue})
- 右补足函数:rpad ({stringValue},{length},{appendValue})
字符串分割函数
split ({stringValue},{splitValue})
四、Hive自定义函数
准备工作
在Eclipse中新建普通java项目
新建文件夹lib,将hive-exec.1.2.2.jar(jar包在hive安装包的lib目录下)复制到lib中,并且添加至构建路径
由于编写了一个自定义解析JSON对象类,所以需要将json依赖的两个jar包导入到hive安装路径的lib目录中
ezmorph-1.0.6.jar
json-lib-2.2.2-jdk15.jar
编写代码
获取子字符串类SubString.java,需要继承UDF类,并且需要创建方法evaluate,可以自定义返回值类型和参数列表,但是方法名必须是evaluate
import org.apache.hadoop.hive.ql.exec.UDF;public class SubString extends UDF{ public String evaluate(String str, int start, int end) {return str.substring(start, end); } }自定义解析JSON对象类JsonParse.java
import org.apache.hadoop.hive.ql.exec.UDF;import net.sf.json.JSONObject;public class JsonParse extends UDF{ public static String evaluate(String jsonStr, String key) { return JSONObject.fromObject(jsonStr).get(key).toString(); } }
打包上传
右键项目选择导出,类型为jar file,只需要打包src目录下的内容即可,命名udf.jar
使用Xftp将udf.jar上传至CentOS
运行测试
注意:自定义函数加载仅对当前会话有效
启动hive客户端
加载jar包,将当前jar包添加至构建路径(类的搜索加载路径)中
add jar /home/bigdata/udf.jar
创建函数
create temporary function sub as ‘com.cry.udf.SubString’;
create temporary function jsonParse as ‘com.cry.udf.JsonParse’;

可以通过以下命令查看函数是否创建成功
show functions;
根据定义的函数名使用select执行,并传入正确的参数
select sub(‘abcdefg’,0,7);
select sub(‘abcdefg’,1,6);

select jsonParse(‘{\”name\”:\”cry\”,\”age\”:20}’,’name’);

其他事项
删除函数
drop temporary function {functionName};
配置文件加载
在hive-site.xml中配置指定目录,可以省略导入jar包操作,需要将jar包放在指定目录下
<property><name>hive.aux.jars.pathname><value>$HIVE_HOME/auxlibvalue> property>初始化文件加载
启动hive时指定初始化文件,在文件中添加jar包,创建函数
vi init-hive
add jar /home/bigdata/udf.jar; create temporary function sub as 'com.cry.udf.SubString'; create temporary function jsonParse as 'com.cry.udf.JsonParse';JDBC操作Hive时可以在初始化工具类时加上初始化方法,即可自动加载jar包,创建函数
public void init() {try {statement.execute("add jar /home/bigdata/udf.jar");statement.execute("create temporary function sub as 'com.sand.udf.SubString'");statement.execute("create temporary function jsonParse as 'com.sand.udf.JsonParse'");} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();} }将以上函数添加至构造函数中
public HiveUtil() {open();init(); }
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
