Hive中虽然自带了一些函数,例如max()、avg()、sum()等,但有时候这些函数可能无法满足我们的需要,这时候就可以通过自定义UDF来进行扩展。

开发流程

UDF的开发流程基本有以下步骤:

  1. 继承UDF类或者GenericUDF类;
  2. 重写evaluate()方法并实现函数逻辑;
  3. 打jar包;
  4. 上传到hdfs;
  5. 使用jar创建临时或者永久函数;
  6. 调用函数。

UDF实现

在重写之前,我们首先建立一个Maven工程。具体的方法大家可以参考我以前的一篇文章:
Hadoop的环境变量配置及与java的交互 创建完成后,需要下载两个包:

<dependency>
      <groupId>org.apache.hadoop</groupId>
      <artifactId>hadoop-common</artifactId>
      <version>2.6.0</version>
    </dependency>
    <dependency>
      <groupId>org.apache.hive</groupId>
      <artifactId>hive-exec</artifactId>
      <version>1.2.1</version>
    </dependency>

注意版本要和自身的一致。
我们就来实现字母的全转大写这一方法:
1、建立一个Big类,继承UDF,编写evaluate方法:
如果文档值为空,则返回空值,如果有字母,则转为其大写输出,其他类型的数值则直接返回

public class Big extends UDF {
    public Text evaluate(Text str) {
        if (str == null) {
            return null;
        }
        return new Text(str.toString().toUpperCase());
    }
}

方法写好后打jar包先放到linux上去,再上传到hdfs。
我这里创建了一个文件路径:

hdfs dfs -mkdir -p /test/hive/functions

上传文件:

hdfs dfs -put UDFexercise.jar /test/hive/functions

临时函数
首先我们创建一个临时函数:
在Hive命令行使用 add jar jar包路径,把jar包加载到临时系统中

add jar /root/UDFexercise.jar;

然后实现这一函数:
create temporary function 函数名 as '方法的全路径’

create temporary function Big as 'Test.work.Big';

注意:此时如果报错可用以下方法解决。
下载zip包

yum install -y zip

删除META_INF包:
*zip -d jar包 ‘META-INF/.SF’ ‘META-INT/.RSA’ 'META-INF/SF’

zip -d UDFexercise.jar 'META-INF/.SF' 'META-INT/.RSA' 'META-INF/*SF';

然后退出hive再重新进入,再次执行以下步骤:

add jar /root/UDFexercise.jar;
create temporary function Big as 'Test.work.Big';

即可成功

hive建表 字段大写转成小写 hive 大写函数_hive


我们可以直接通过select来实现这一方法:

select Big('abc');

hive建表 字段大写转成小写 hive 大写函数_java_02


永久函数

前面的步骤不变,当上传到hdfs后,我们选择需要用到的数据库。

use test;

创建永久函数的指令:
create function 函数名 as ‘方法的全路径’
using jar ‘hdfs:/主机名:9000/jar包的hdfs路径’;

create function Big as 'Test.work.Big' using jar 'hdfs://hadoop01:9000/test/hive/functions/UDFexercise.jar';

hive建表 字段大写转成小写 hive 大写函数_hive_03


创建成功后,我们就可以永久调用此函数:

select Big('abc');

hive建表 字段大写转成小写 hive 大写函数_java_04


我们再举个例子。在一个时间的基础上,加上小时后得出新的时间。

public class Hour extends UDF {
    public Text evaluate(Text times, IntWritable hours) throws ParseException {
        //把接收到的数据转换成java类型
        String str = times.toString();
        int i = hours.get();
        //日期格式
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        //把字符串转换成Date类型
        Date d = sdf.parse(str);
        //计算时间,小时i*60分钟*60秒*1000毫秒得到新的时间,再把新的时间转成固定格式
        String rst = sdf.format(new Date(d.getTime() + i * 60 * 60 * 1000));
        return new Text(rst);
    }
}

打成jar包上传后,根据上述方法建立临时/永久函数:

add jar /test/UDFexercise.jar;
create temporary function time as 'Test.work.Hour';
select time('2020-09-22 12:00:00',200);

hive建表 字段大写转成小写 hive 大写函数_java_05

临时UDF和永久UDF的区别

1、当我们创建一个临时UDF后,如果退出系统,那么这个函数也将消失,如果想要调用,需要登录上重新创建;而永久性的UDF函数则会一直存在;
2、临时UDF可以在任意库中直接调用,不受库限制;而永久性UDF函数在如果想要再其他库调用需要在函数名前加上库名。
例如,我在test库创建了一个永久性的Big函数,那么在其他库调用的时候需要这样写

select test.Big('abc');

才能执行成功。