1.说明
官方文档:https://cwiki.apache.org/confluence/display/Hive/HivePlugins
根据用户自定义函数类别分为以下三种:
(1)UDF(User-Defined-Function)
一进一出。
(2)UDAF(User-Defined Aggregation Function)
用户自定义聚合函数,多进一出。
类似于:count/max/min
(3)UDTF(User-Defined Table-Generating Functions)
用户自定义表生成函数,一进多出。
如lateral view explode()
2.编程步骤
(0)需求:自定义一个手机号脱敏需求
(1)pom导入hive依赖
<dependencies> <dependency> <groupId>org.apache.hive</groupId> <artifactId>hive-exec</artifactId> <version>3.1.3</version> </dependency> </dependencies>
(2)继承hive提供的类
org.apache.hadoop.hive.ql.udf.generic.GenericUDF
org.apache.hadoop.hive.ql.udf.generic.GenericUDTF;
(3)实现类中的抽象方法
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.primitive.PrimitiveObjectInspectorFactory; import java.util.regex.Matcher; import java.util.regex.Pattern; public class EncryptPhoneNumber extends GenericUDF { // 初始化方法,在真正执行计算之前会调用一次 @Override public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { if(arguments.length!=1){ throw new UDFArgumentException("只能接收一个参数"); } ObjectInspector argument = arguments[0]; if(argument.getCategory()!=ObjectInspector.Category.PRIMITIVE){ throw new UDFArgumentException("只能接收基本数据类型的参数"); } PrimitiveObjectInspector primitiveObjectInspector = (PrimitiveObjectInspector) argument; if(primitiveObjectInspector.getPrimitiveCategory()!=PrimitiveObjectInspector.PrimitiveCategory.STRING){ throw new UDFArgumentException("只能接收STRING类型的参数"); } return PrimitiveObjectInspectorFactory.javaStringObjectInspector; } // 每行数据调用一下这个方法,数据的计算逻辑主要在这里实现 @Override public Object evaluate(DeferredObject[] arguments) throws HiveException { DeferredObject argument = arguments[0]; if (argument.get() != null) { String phone = argument.get().toString(); //判断手机号是否为11位 if (phone.length() == 11) { //判断数据是否满足中国大陆手机号码规范 String regex = "^(1[3-9]\\d{9}$)"; Pattern p = Pattern.compile(regex); Matcher m = p.matcher(phone); if (m.matches()) { //进入这里都是符合手机号规则的 StringBuilder sb = new StringBuilder(phone); sb.replace(3, 7, "xxxx"); return sb; } else { //不符合手机号规则 数据直接原封不动返回 return phone; } } else { return phone; } }else{ return null; } } // 自定义函数如果要在执行计划里面进行展示,就在这里定义要展示的内容,通常自定义函数没有展示需求 @Override public String getDisplayString(String[] children) { return "这是hive自定义函数,实现手机号脱敏功能"; } }
3.服务侧配置
打成jar包上传到服务器/opt/module/hive/datas/EncryptPhoneNumber.jar
3.1.创建临时函数
1、将jar包添加到hive的classpath,临时生效
hive (default)> add jar /opt/module/hive/datas/EncryptPhoneNumber.jar;
2、创建临时函数与开发好的java class关联
hive (default)> create temporary function EncryptPhoneNumber as "com.fblinux.hive.udf.EncryptPhoneNumber";
3、即可在hql中使用自定义的临时函数
hive> select EncryptPhoneNumber(13511111111); FAILED: SemanticException [Error 10014]: Line 1:7 Wrong arguments '13511111111': 只能接收STRING类型的参数 hive> select EncryptPhoneNumber("13511111111"); OK 135xxxx1111 hive> select EncryptPhoneNumber("23511111111"); OK 23511111111
4、删除临时函数
hive (default)> drop temporary function EncryptPhoneNumber;
注意:临时函数只跟会话有关系,跟库没有关系。只要创建临时函数的会话不断,在当前会话下,任意一个库都可以使用,其他会话全都不能使用。
3.2.创建永久函数
1、创建永久函数
注意:因为add jar本身也是临时生效,所以在创建永久函数的时候,需要制定路径(并且因为元数据的原因,这个路径还得是HDFS上的路径)。
hive (default)> create function EncryptPhoneNumber as "com.fblinux.hive.udf.EncryptPhoneNumber" using jar "hdfs://hadoop01:8020/udf/EncryptPhoneNumber.jar";
2、即可在hql中使用自定义的永久函数
hive> select EncryptPhoneNumber(13511111111); FAILED: SemanticException [Error 10014]: Line 1:7 Wrong arguments '13511111111': 只能接收STRING类型的参数 hive> select EncryptPhoneNumber("13511111111"); OK 135xxxx1111 hive> select EncryptPhoneNumber("23511111111"); OK 23511111111
3、删除永久函数
hive (default)> drop function EncryptPhoneNumber;
注意:永久函数跟会话没有关系,创建函数的会话断了以后,其他会话也可以使用。
永久函数创建的时候,在函数名之前需要自己加上库名,如果不指定库名的话,会默认把当前库的库名给加上。
永久函数使用的时候,需要在指定的库里面操作,或者在其他库里面使用的话加上,库名.函数名。
3.3.执行计划内容验证
hive> explain select EncryptPhoneNumber("13511111111"); OK STAGE DEPENDENCIES: Stage-0 is a root stage STAGE PLANS: Stage: Stage-0 Fetch Operator limit: -1 Processor Tree: TableScan alias: _dummy_table Row Limit Per Split: 1 Statistics: Num rows: 1 Data size: 10 Basic stats: COMPLETE Column stats: COMPLETE Select Operator expressions: 这是hive自定义函数,实现手机号脱敏功能 (type: string) outputColumnNames: _col0 Statistics: Num rows: 1 Data size: 95 Basic stats: COMPLETE Column stats: COMPLETE ListSink
4.知识点
1、要是在自定义函数场景中碰到自己不会写的功能,可以通过如下方式,查询hive自带的函数在源码的路径,进行参考
hive> desc function extended upper; OK upper(str) - Returns str with all characters changed to uppercase Synonyms: ucase Example: > SELECT upper('Facebook') FROM src LIMIT 1; 'FACEBOOK' Function class:org.apache.hadoop.hive.ql.udf.generic.GenericUDFUpper //hive 自带函数源码的位置 Function type:BUILTIN
转载请注明:西门飞冰的博客 » hive 自定义UDF函数