第一章 自定义函数类别
1.1 UDF(User-Defined-Function)
一进一出。
1.2 UDAF(User-Defined Aggregation Function)
用户自定义聚合函数,多进一出。类似于count/max/min
1.3 UDTF(User-Defined Table-Generating Functions)
用户自定义表生成函数,一进多出。如lateral view explode()
第二章 操作
自定义一个UDF实现计算给定基本数据类型的长度,实现
sql
select my_len("abcd"); --4
2.1 创建一个 Maven 工程 Hive
2.2 导入依赖(hive版本根据生产具体的版本)
xml
<dependencies>
<dependency>
<groupId>org.apache.hive</groupId>
<artifactId>hive-exec</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>
2.3 创建一个类(实现三个抽象方法)
java
package com.kgl.hive.udf;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector.PrimitiveCategory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
/**
* 自定义Hive UDF:计算输入字符串的长度
* 仅支持String类型参数,逻辑清晰、类型校验完善,便于在Hive SQL中直接调用
*/
public class my_length extends GenericUDF {
/**
* 初始化方法:校验输入参数、确定返回值类型
* @param objectInspectors输入参数的ObjectInspector数组
* @return 返回值的ObjectInspector(固定为Java Int类型)
* @throws UDFArgumentException参数校验不通过时抛出异常
*/
@Override
public ObjectInspector initialize(ObjectInspector[] objectInspectors) throws UDFArgumentException {
// 1. 校验参数数量:必须为1个
if (objectInspectors.length != 1) {
throw new UDFArgumentException("自定义函数MyLength仅支持1个参数,实际传入:" + objectInspectors.length);
}
// 2. 提取第一个参数的ObjectInspector
ObjectInspector inspector = objectInspectors[0];
// 3. 校验参数类型:必须是基本类型(Primitive)
if (inspector.getCategory() != ObjectInspector.Category.PRIMITIVE) {
throw new UDFArgumentException("参数必须是基本类型(Primitive),实际类型:" + inspector.getCategory());
}
// 4. 强转为PrimitiveObjectInspector,校验具体类型是否为STRING
PrimitiveObjectInspector primitiveInspector = (PrimitiveObjectInspector) inspector;
if (primitiveInspector.getPrimitiveCategory() != PrimitiveCategory.STRING) {
throw new UDFArgumentException("参数必须是字符串(STRING)类型,实际类型:" + primitiveInspector.getPrimitiveCategory());
}
// 5. 返回值固定为int类型,直接使用工厂类生成
return PrimitiveObjectInspectorFactory.javaIntObjectInspector; //由于是计算长度,需要数字,所以工厂类返回的是int
//return PrimitiveObjectInspectorFactory.javaStringObjectInspector; //如果是转大写,那就是字符串String
}
/**
* 核心计算方法:处理输入参数,返回字符串长度
* @param deferredObjects延迟加载的输入参数对象数组
* @return 字符串长度(int类型),null输入返回0
* @throws HiveException Hive执行异常时抛出
*/
@Override
public Object evaluate(DeferredObject[] deferredObjects) throws HiveException {
// 1. 提取第一个(也是唯一的)参数
DeferredObject deferredObj = deferredObjects[0];
Object inputObj = deferredObj.get();
// 2. 处理 null 输入:直接返回 0
if (inputObj == null) {
return 0;
}
// 3. 非 null 时转为字符串计算长度
return inputObj.toString().length(); //由于是计算长度,返回的是int
//return inputObj.toString().toUpperCase(); //如果是转大写,那就是字符串String
}
/**
* 函数描述方法:用于Hive命令行显示函数信息
* @param strings函数参数描述(这里未用到,保持规范实现)
* @return函数简洁描述
*/
@Override
public String getDisplayString(String[] strings) {
return "MyLength(STR_COL)-计算字符串长度,仅支持字符串类型参数";
}
}
2.4 创建临时函数
2.4.1 打成jar包上传到服务器/opt/module/hive/datas/架包名.jar
2.4.2 将jar包添加到hive的classpath,临时生效
sql
hive (default)>add jar /opt/module/hive/datas/架包名.jar;
2.4.3 创建临时函数与开发好的java class关联
sql
hive (default)> create temporary function my_len as "com.kgl.hive.udf.架包名";
2.4.4 即可在hql中使用自定义的临时函数
sql
hive (default)> select ename,my_len(ename) ename_len from emp;
2.4.5 删除临时函数
sql
hive (default)> drop temporary function my_len;
注意:临时函数只跟会话有关系,跟库没有关系。只要创建临时函数的会话不断,在当前会话下,任意一个库都可以使用,其他会话全都不能使用。
2.5 创建永久函数
2.5.1 创建永久函数
注意: 因为add jar本身也是临时生效,所以在创建永久函数的时候,需要制定路径(并且因为元数据的原因,这个路径还得是HDFS上的路径)。
sql
hive (default)> create function my_len2 as "com.kgl.hive.udf.架包名" using jar "hdfs://hadoop102:8020/udf/架包名.jar";
2.5.2 即可在hql中使用自定义的永久函数
sql
hive (default)> select ename,my_len2(ename) ename_len from emp;
2.5.3 删除永久函数
sql
hive (default)> drop function my_len2;
注意:永久函数跟会话没有关系,创建函数的会话断了以后,其他会话也可以使用。
永久函数创建的时候,在函数名之前需要自己加上库名,如果不指定库名的话,会默认把当前库的库名给加上。
永久函数使用的时候,需要在指定的库里面操作,或者在其他库里面使用的话加上,库名.函数名。
第三章 IDEA使用
IDE没有加载Maven或者无法创建类
3.1 重新导入Maven项目
3.1.1 在IDEA中打开D:\maven_test\hive-udf\hive-udf目录
3.1.2 找到pom.xml文件
3.1.3 右键点击pom.xml → 选择 "Add as Maven Project" 或"Reload Project"
3.1.4 或者"Maven"→"Reload Project"或"Reimport"(如果右键菜单没有New选项,可能是因为目录没有被识别。
重新加载Maven项目:打开右侧的Maven面板,点击刷新按钮,或者删除.idea文件夹重新导入:关闭IDEA,删除.idea文件夹和*.iml 文件重新用IDEA打开pom.xml)
3.1.5 或者点击右侧Maven工具栏的刷新按钮
3.1.6 使用命令行
xml
cd D:/maven_test/hive-udf/hive-udf
mvn clean install
3.2 确保目录标记正确
打开Project Structure(Ctrl + Alt + Shift + S)
检查Modules → 确保src/main/java被标记为Sources(蓝色)
3.3 创建类的正确位置在IDEA的项目视图中:
xml
hive-udf
└── src
└── main
└── java
└── com
└── kgl
└── [在这里右键]