Todos os produtos
Search
Central de documentação

MaxCompute:Java UDTF

Última atualização: Sep 22, 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ógicas personalizadas. Ao aproveitar os recursos da linguagem Java, você atende melhor aos requisitos específicos de processamento de dados, o que melhora tanto a eficiência do desenvolvimento quanto o desempenho do processamento. Este tópico descreve a estrutura do código, o uso e os exemplos de UDTFs em Java.

Estrutura de código da UDTF

Você pode 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.

    Você pode organizar 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 usar outras classes UDTF ou tipos de dados complexos, adicione as classes necessárias de acordo com 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 a sua lógica de negócios.

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

    O formato é @Resolve(<signature>). O 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 pode 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 de acordo com as suas necessidades.

    API

    Descrição

    public void setup(ExecutionContext ctx) throws UDFException

    O método de inicialização. O MaxCompute chama a 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 são os parâmetros de entrada especificados para a UDTF na instrução SQL. Os parâmetros de entrada são passados como um array Object[], e a saída é gerada usando a função forward. Você deve chamar a função forward dentro da função process para determinar a saída.

    Nota

    A falha ao chamar forward a partir do método process ou close pode causar perda de dados. Por exemplo, se uma thread em segundo plano executar uma chamada forward, você deve garantir que o método process não termine até que a chamada forward seja concluída, a fim de evitar a perda de dados.

    public void close() throws UDFException

    O 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, em que cada chamada ao forward gera um registro. Ao chamar uma UDTF em uma consulta SQL, use a cláusula as para renomear a saída do forward.

    Ao escrever uma UDTF em Java, você pode usar Java Type ou Java Writable Type. Para obter um mapeamento detalhado entre os tipos de dados suportados pelo MaxCompute e os tipos de dados Java, consulte Data types.

A seguir, 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 podem acessar a Internet. Ative o acesso à Internet preenchendo 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 com você para estabelecer a conexão. Para obter detalhes, consulte Network connection process.

  • Nenhuma outra coluna no mesmo SELECT: Uma instrução SELECT que chama uma UDTF não pode fazer referência a outras colunas ou expressões. A instrução a seguir é inválida:

    -- Invalid: mixes a UDTF with another column
    select value, user_udtf(key) as mycol ...
  • Sem aninhamento: As UDTFs não podem ser aninhadas dentro de outras UDTFs. A instrução a seguir é inválida:

    -- Invalid: user_udtf2 is nested inside user_udtf1
    select user_udtf1(user_udtf2(key)) as mycol...;
  • Incompatível com GROUP BY, DISTRIBUTE BY e SORT BY: Uma UDTF não pode aparecer na mesma instrução SELECT que essas cláusulas. A instrução a seguir é 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 o seguinte:

  • 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 a UDTF1 e a 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 os valores NULL do SQL são passados como null do Java, o que os tipos primitivos não podem 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 em relação a essa assinatura e relata um erro se encontrar uma incompatibilidade de tipo. O formato é o seguinte.

'arg_type_list -> type_list'

Em que:

  • type_list: Representa os tipos de dados dos valores de retorno. Uma UDTF pode retornar várias colunas. Os tipos de dados suportados são 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. Especifique vários parâmetros de entrada, separados por vírgulas (,). Os tipos de dados suportados são 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.

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

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

    • Se o arg_type_list for uma string vazia (''), isso 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 mostra exemplos de anotações @Resolve válidas.

Exemplo

Descrição

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

Os tipos de parâmetro de entrada são BIGINT e BOOLEAN. Os tipos de valor de retorno são STRING e DATETIME.

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

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

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

A função não possui parâmetros de entrada. Os tipos de valor 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 de parâmetro de entrada são ARRAY, STRUCT e STRING. Os tipos de valor de retorno são MAP e STRUCT.

Tipos de dados

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

Ao escrever uma UDTF em Java, certifique-se de que os tipos de dados usados sejam mapeados corretamente para aqueles suportados pelo MaxCompute. A tabela a seguir descreve esses mapeamentos.

Tipo do 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 para valores de entrada ou retorno da UDTF, o seu projeto MaxCompute deve usar a edição de tipo de dados do MaxCompute 2.0.

Uso

Após desenvolver uma UDTF em Java seguindo o development process, você pode chamá-la no MaxCompute SQL.

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

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

Para obter um passo a passo 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 do MaxCompute. Para obter mais informações, consulte os seguintes tópicos:

    1. Instale o MaxCompute Studio

    2. Connect to a MaxCompute project

    3. Crie um módulo Java do MaxCompute

  2. Escreva o código da UDTF.

    1. No explorador Project, clique em src > main > java (diretório source) com o botão direito do mouse 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.

      O Name é o nome da classe Java do MaxCompute a ser criada. Se um pacote ainda não tiver sido criado, insira packagename.classname aqui para gerar um pacote automaticamente.

    3. No editor de código, insira o código a seguir. Este é um exemplo de código de 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 Execute e depure uma UDF localmente.

    Clique em MyUDTF com o botão direito do mouse na árvore do projeto e selecione Execute '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, Limite de baixe de registros como 100 e Data Column Separator como |. Em seguida, clique em OK.

    Nota

    Você pode usar 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 do 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 MyUDTF com o botão direito do mouse e selecione Deploy to server.... Na caixa de diálogo Empacote um jar, envie o recurso e registre a função, selecione o MaxCompute project de destino, confirme o caminho do Resource file, defina a Main class como a classe UDTF correspondente (por exemplo, org.alidata.odps.udtf.examples.MyUDTF), insira user_udtf para Function name, selecione Forçar atualize se já existir 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 MaxCompute project com o botão direito do mouse, inicie o cliente do 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.