Todos os produtos
Search
Central de documentação

MaxCompute:UDTF em Java

Última atualização: Aug 21, 2026

Escrever uma função de tabela definida pelo usuário (UDTF) em Java é uma forma eficaz de lidar com tarefas complexas de processamento de dados e implementar lógica personalizada. Ao aproveitar os recursos da linguagem Java, você atende melhor a requisitos específicos de processamento de dados, aumentando tanto a eficiência do desenvolvimento quanto o desempenho do processamento. Este tópico descreve a estrutura de código, o uso e exemplos de UDTFs em Java.

Estrutura de código da UDTF

É possível escrever o código da UDTF em Java usando o IntelliJ IDEA (Maven) ou MaxCompute Studio. O código deve incluir os seguintes componentes:

  • Pacote Java: Opcional.

    Organize suas classes Java em um pacote para facilitar a localização e o uso.

  • Estender a classe UDTF: Obrigatório.

    As classes necessárias são com.aliyun.odps.udf.UDTF, com.aliyun.odps.udf.annotation.Resolve (para a anotação @Resolve) e com.aliyun.odps.udf.UDFException (para métodos na classe Java). Caso precise utilizar outras classes UDTF ou tipos de dados complexos, adicione as classes necessárias conforme MaxCompute UDF overview.

  • Classe Java personalizada: Obrigatório.

    Esta é a unidade organizacional do código da UDTF. Ela define as variáveis e os métodos que implementam sua lógica de negócios.

  • Anotação @Resolve: Obrigatório.

    O formato é @Resolve(<signature>). signature é uma assinatura de função que define os tipos de dados dos parâmetros de entrada e do valor de retorno. Uma UDTF não consegue obter a assinatura da função por reflexão e deve usar a anotação @Resolve para especificá-la, por exemplo, @Resolve("smallint->varchar(10)"). Para obter mais informações sobre a anotação @Resolve, consulte @Resolve annotation.

  • Implementar métodos na classe Java: Obrigatório.

    A implementação da classe Java inclui os quatro métodos a seguir. Escolha implementá-los conforme suas necessidades.

    API

    Descrição

    public void setup(ExecutionContext ctx) throws UDFException

    Método de inicialização. O MaxCompute chama sua lógica de inicialização personalizada antes que a UDTF comece a processar os dados de entrada. O método setup é chamado uma vez por worker.

    public void process(Object[] args) throws UDFException

    A função process é chamada uma vez para cada registro em uma consulta SQL. Os parâmetros da função process correspondem aos parâmetros de entrada especificados para a UDTF na instrução SQL. Esses parâmetros são passados como um array Object[], e a saída é gerada por meio da função forward. É obrigatório chamar a função forward dentro da função process para determinar a saída.

    Nota

    Deixar de chamar forward no método process ou close pode causar perda de dados. Por exemplo, se uma thread em segundo plano executar uma chamada forward, garanta que o método process não termine até que a chamada forward seja concluída, evitando assim a perda de dados.

    public void close() throws UDFException

    Método de encerramento da UDTF. Ele é chamado apenas uma vez, após o processamento do último registro.

    public void forward(Object …o) throws UDFException

    Chame o método forward para gerar dados de saída; cada chamada a forward produz um registro. Ao chamar uma UDTF em uma consulta SQL, utilize a cláusula as para renomear a saída de forward.

    Ao escrever uma UDTF em Java, utilize Java Type ou Java Writable Type. Para obter o mapeamento detalhado entre os tipos de dados suportados pelo MaxCompute e os tipos de dados Java, consulte Data types.

Abaixo está um exemplo de UDTF.

// Organize the defined Java class in the org.alidata.odps.udtf.examples package.
package org.alidata.odps.udtf.examples;
// Extend the UDTF class.
import com.aliyun.odps.udf.UDTF;
import com.aliyun.odps.udf.UDTFCollector;
import com.aliyun.odps.udf.annotation.Resolve;
import com.aliyun.odps.udf.UDFException;
// Custom Java class.
//@Resolve annotation.
@Resolve("string,bigint->string,bigint")
public class MyUDTF extends UDTF {     
     // Implement the methods of the Java class.
     @Override
     public void process(Object[] args) throws UDFException {
         String a = (String) args[0];
         Long b = (Long) args[1];
         for (String t: a.split("\\s+")) {
         forward(t, b);
       }
     }
   }

Limitações

  • Acesso à Internet: Por padrão, as UDFs não têm acesso à Internet. Para ative esse acesso, preencha o formulário de solicitação de conexão de rede. Após a aprovação, a equipe de suporte técnico do MaxCompute entrará em contato para estabelecer a conexão. Para mais detalhes, consulte Network connection process.

  • Proibição de outras colunas no mesmo SELECT: Uma instrução SELECT que chame uma UDTF não pode referenciar outras colunas ou expressões. A seguinte instrução é inválida:

    -- Invalid: mixes a UDTF with another column
    select value, user_udtf(key) as mycol ...
  • Proibição de aninhamento: Não é permitido aninhar UDTFs dentro de outras UDTFs. A seguinte instrução é inválida:

    -- Invalid: user_udtf2 is nested inside user_udtf1
    select user_udtf1(user_udtf2(key)) as mycol...;
  • Incompatibilidade com GROUP BY, DISTRIBUTE BY e SORT BY: Uma UDTF não pode aparecer na mesma instrução SELECT que contenha essas cláusulas. A seguinte instrução é inválida:

    -- Invalid: UDTF used with GROUP BY
    select user_udtf(key) as mycol ... group by mycol;

Considerações

Ao escrever uma UDTF em Java, observe os pontos a seguir:

  • Evite definir classes com o mesmo nome, mas com lógicas de implementação diferentes, em pacotes JAR de UDTF distintos. Por exemplo, suponha que UDTF1 e UDTF2 correspondam aos recursos de pacote JAR udtf1.jar e udtf2.jar, respectivamente. Se ambos os pacotes JAR contiverem uma classe chamada com.aliyun.UserFunction.class com lógicas diferentes, o MaxCompute carregará aleatoriamente uma das classes quando UDTF1 e UDTF2 forem chamadas na mesma instrução SQL. Isso pode causar resultados inesperados ou falhas de compilação.

  • Os parâmetros de entrada e os valores de retorno devem usar tipos de objeto Java, como String e Long, em vez de tipos primitivos.

  • Isso ocorre porque valores SQL NULL são passados como null em Java, o que tipos primitivos não conseguem representar.

Anotação @Resolve

O formato da anotação @Resolve é o seguinte:

@Resolve(<signature>)

A string signature especifica os tipos de dados dos parâmetros de entrada e dos valores de retorno da UDTF. Durante a análise da consulta, o MaxCompute valida as chamadas com base nessa assinatura e relata um erro caso encontre incompatibilidade de tipos. O formato é o seguinte:

'arg_type_list -> type_list'

Onde:

  • type_list: Representa os tipos de dados dos valores de retorno. Uma UDTF pode retornar várias colunas. Os tipos de dados suportados incluem BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(precision,scale), tipos de dados complexos (ARRAY, MAP, STRUCT) e tipos de dados complexos aninhados.

  • arg_type_list: Representa os tipos de dados dos parâmetros de entrada. É possível especificar múltiplos parâmetros de entrada, separados por vírgulas (,). Os tipos de dados suportados incluem BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(precision,scale), CHAR, VARCHAR, tipos de dados complexos (ARRAY, MAP, STRUCT) e tipos de dados complexos aninhados.

    arg_type_list também aceita um asterisco (*) ou uma string vazia ('').

    • Se arg_type_list for um asterisco (*), indica que a função aceita qualquer número de parâmetros de entrada.

    • Se arg_type_list for uma string vazia (''), indica que a função não possui parâmetros de entrada.

    Para obter mais informações sobre a sintaxe estendida da anotação Resolve, consulte Dynamic parameters for UDAFs and UDTFs.

A tabela a seguir apresenta exemplos de anotações @Resolve válidas.

Exemplo

Descrição

@Resolve('bigint,boolean->string,datetime')

Os tipos dos parâmetros de entrada são BIGINT e BOOLEAN. Os tipos dos valores de retorno são STRING e DATETIME.

@Resolve('*->string, datetime')

A função aceita qualquer número de parâmetros de entrada. Os tipos dos valores de retorno são STRING e DATETIME.

@Resolve('->double, bigint, string')

A função não possui parâmetros de entrada. Os tipos dos valores de retorno são DOUBLE, BIGINT e STRING.

@Resolve("array<string>,struct<a1:bigint,b1:string>,string->map<string,bigint>,struct<b1:bigint>")

Os tipos dos parâmetros de entrada são ARRAY, STRUCT e STRING. Os tipos dos valores de retorno são MAP e STRUCT.

Tipos de dados

Os tipos de dados suportados pelo MaxCompute variam conforme a edição do tipo de dados. A partir do MaxCompute 2.0, tipos adicionais estão disponíveis, incluindo tipos complexos como ARRAY, MAP e STRUCT. Para mais informações, consulte Data type editions.

Ao escrever uma UDTF em Java, assegure-se de que os tipos de dados utilizados tenham o mapeamento correto para aqueles suportados pelo MaxCompute. A tabela a seguir descreve esses mapeamentos.

Tipo MaxCompute

Tipo Java

Tipo Java Writable

TINYINT

java.lang.Byte

ByteWritable

SMALLINT

java.lang.Short

ShortWritable

INT

java.lang.Integer

IntWritable

BIGINT

java.lang.Long

LongWritable

FLOAT

java.lang.Float

FloatWritable

DOUBLE

java.lang.Double

DoubleWritable

DECIMAL

java.math.BigDecimal

BigDecimalWritable

BOOLEAN

java.lang.Boolean

BooleanWritable

STRING

java.lang.String

Text

VARCHAR

com.aliyun.odps.data.Varchar

VarcharWritable

BINARY

com.aliyun.odps.data.Binary

BytesWritable

DATE

java.sql.Date

DateWritable

DATETIME

java.util.Date

DatetimeWritable

TIMESTAMP

java.sql.Timestamp

TimestampWritable

INTERVAL_YEAR_MONTH

N/A

IntervalYearMonthWritable

INTERVAL_DAY_TIME

N/A

IntervalDayTimeWritable

ARRAY

java.util.List

N/A

MAP

java.util.Map

N/A

STRUCT

com.aliyun.odps.data.Struct

N/A

Nota

Para usar Java Writable Types como entrada ou retorno de valores da UDTF, seu projeto MaxCompute deve utilizar a edição de tipos de dados do MaxCompute 2.0.

Uso

Após desenvolver uma UDTF em Java seguindo as instruções em development process, chame-a no MaxCompute SQL.

  • Usar uma UDF em um projeto MaxCompute: O método é semelhante ao uso de built-in functions. Utilize uma função definida pelo usuário da mesma maneira que uma função integrada.

  • Usar uma UDF entre projetos: Utilize uma UDF do Projeto B no Projeto A. A seguinte instrução mostra um exemplo: select B:udf_in_other_project(arg0, arg1) as res from table_t;. Para obter mais informações sobre compartilhamento entre projetos, consulte Cross-project resource access based on packages.

Para obter um tutorial completo sobre como desenvolver e chamar uma UDTF em Java usando o MaxCompute Studio, consulte Usage example.

Exemplo de uso

O procedimento a seguir orienta você no desenvolvimento e na chamada de uma UDTF em Java usando o MaxCompute Studio:

  1. Prepare o ambiente.

    Antes de desenvolver e depurar uma UDF no MaxCompute Studio, instale o MaxCompute Studio e conecte-o a um projeto MaxCompute. Para mais informações, consulte os seguintes tópicos:

    1. Install MaxCompute Studio

    2. Connect to a MaxCompute project

    3. Create a MaxCompute Java module

  2. Escreva o código da UDTF.

    1. No explorador Project, clique em com o botão direito no diretório de source do módulo (src > main > java) e selecione New > MaxCompute Java.

    2. Na caixa de diálogo Create new MaxCompute java class, clique em UDTF, insira um Name e pressione Enter. Por exemplo, nomeie a classe Java como MyUDTF.

      Name corresponde ao nome da classe Java do MaxCompute a ser criada. Se nenhum pacote tiver sido criado, insira packagename.classname neste campo para gerar automaticamente um pacote.

    3. No editor de código, insira o código a seguir. Trata-se de um exemplo de código UDTF.

      package org.alidata.odps.udtf.examples;
      import com.aliyun.odps.udf.UDTF;
      import com.aliyun.odps.udf.UDTFCollector;
      import com.aliyun.odps.udf.annotation.Resolve;
      import com.aliyun.odps.udf.UDFException;
      // TODO define input and output types, e.g., "string,string->string,bigint".
         @Resolve("string,bigint->string,bigint")
         public class MyUDTF extends UDTF {
           @Override
           public void process(Object[] args) throws UDFException {
             String a = (String) args[0];
             Long b = (Long) args[1];
             for (String t: a.split("\\s+")) {
               forward(t, b);
             }
           }
         }
  3. Execute e depure a UDTF localmente para garantir que o código funcione conforme o esperado.

    Para obter mais informações sobre depuração, consulte Run and debug a UDF locally.

    Clique em com o botão direito no arquivo MyUDTF na árvore do projeto e selecione Run 'MyUDTF.main()'. Na caixa de diálogo Run/Debug Configurations, defina MaxCompute project como local, MaxCompute table como wc_in2, Table partition como p2=1,p1=2, Table columns como colc,colb, Download Record limit como 100 e Data Column Separator como |. Em seguida, clique em OK.

    Nota

    Utilize os parâmetros anteriores para a execução de exemplo.

  4. Empacote a UDTF em um pacote JAR, faça o upload para o seu projeto MaxCompute e registre a função. Para este exemplo, nomeie a função como user_udtf.

    Para obter mais informações sobre empacotamento, consulte Procedure.

    Na árvore de projetos do IntelliJ IDEA, clique em com o botão direito no arquivo Java da UDTF (por exemplo, MyUDTF) e selecione Deploy to server.... Na caixa de diálogo Package a jar, submit resource and register function, selecione o MaxCompute project de destino, confirme o caminho do Resource file, defina Main class como a classe UDTF correspondente (por exemplo, org.alidata.odps.udtf.examples.MyUDTF), insira user_udtf em Function name, selecione Force update if already exists e clique em OK para concluir a implantação.

  5. No painel de navegação à esquerda do MaxCompute Studio, clique em Project Explorer. Clique em com o botão direito no projeto MaxCompute de destino, inicie o cliente MaxCompute e execute um comando SQL para chamar a UDTF recém-criada.

    Suponha que a tabela de destino, my_table, contenha os seguintes dados:

    +------------+------------+
    | col0       | col1       |
    +------------+------------+
    | A B        | 1          |
    | C D        | 2          |
    +------------+------------+

    Execute o seguinte comando SQL para chamar a UDTF.

    select user_udtf(col0, col1) as (c0, c1) from my_table;

    O seguinte resultado é retornado.

    +----+------------+
    | c0 | c1         |
    +----+------------+
    | A  | 1          |
    | B  | 1          |
    | C  | 2          |
    | D  | 2          |
    +----+------------+

Documentação relacionada

Para obter mais exemplos de uso de UDTFs em Java, consulte Java UDTF examples.