第一章 自定义函数类别

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实现计算给定基本数据类型的长度,实现

select my_len("abcd"); --4

2.1 创建一个 Maven 工程 Hive
2.2 导入依赖(hive版本根据生产具体的版本)

<dependencies>
    <dependency>
        <groupId>org.apache.hive</groupId>
        <artifactId>hive-exec</artifactId>
        <version>3.1.3</version>
    </dependency>
</dependencies>

2.3 创建一个类(实现三个抽象方法)

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,临时生效

hive (default)>add jar /opt/module/hive/datas/架包名.jar;

2.4.3 创建临时函数与开发好的java class关联

hive (default)> create temporary function my_len as "com.kgl.hive.udf.架包名";

2.4.4 即可在hql中使用自定义的临时函数

hive (default)> select ename,my_len(ename) ename_len from emp;

2.4.5 删除临时函数

hive (default)> drop temporary function my_len;

注意:临时函数只跟会话有关系,跟库没有关系。只要创建临时函数的会话不断,在当前会话下,任意一个库都可以使用,其他会话全都不能使用。
2.5 创建永久函数
2.5.1 创建永久函数
注意: 因为add jar本身也是临时生效,所以在创建永久函数的时候,需要制定路径(并且因为元数据的原因,这个路径还得是HDFS上的路径)。

hive (default)> create function my_len2 as "com.kgl.hive.udf.架包名" using jar "hdfs://hadoop102:8020/udf/架包名.jar";

2.5.2 即可在hql中使用自定义的永久函数

hive (default)> select ename,my_len2(ename) ename_len from emp;

2.5.3 删除永久函数

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 使用命令行

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的项目视图中:

hive-udf
  └── src
      └── main
          └── java
              └── com
                  └── kgl
                      └── [在这里右键]
Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐