Tous les produits
Search
Centre de documentation

MaxCompute:UDTF Java

Dernière mise à jour :Aug 21, 2026

L'écriture d'une fonction de table définie par l'utilisateur (UDTF) en Java constitue une méthode efficace pour traiter des tâches complexes de traitement des données et mettre en œuvre une logique personnalisée. En tirant parti des fonctionnalités du langage Java, vous pouvez mieux répondre à des besoins spécifiques de traitement des données, améliorant ainsi l'efficacité du développement et les performances de traitement. Cette rubrique décrit la structure du code, l'utilisation et des exemples d'UDTF Java.

Structure du code UDTF

Vous pouvez écrire le code UDTF en Java à l'aide d'IntelliJ IDEA (Maven) ou de MaxCompute Studio. Le code doit inclure les composants suivants :

  • Package Java : facultatif.

    Organisez vos classes Java dans un package afin de faciliter leur recherche et leur utilisation.

  • Extension de la classe UDTF : obligatoire.

    Les classes requises sont com.aliyun.odps.udf.UDTF, com.aliyun.odps.udf.annotation.Resolve (pour l'annotation @Resolve) et com.aliyun.odps.udf.UDFException (pour les méthodes de la classe Java). Si vous devez utiliser d'autres classes UDTF ou des types de données complexes, ajoutez les classes requises conformément à la section Présentation des UDF MaxCompute.

  • Classe Java personnalisée : obligatoire.

    Il s'agit de l'unité organisationnelle du code UDTF. Elle définit les variables et les méthodes qui mettent en œuvre votre logique métier.

  • Annotation @Resolve : obligatoire.

    Le format est @Resolve(<signature>). La signature est une signature de fonction qui définit les types de données des paramètres d'entrée et de la valeur de retour. Une UDTF ne peut pas obtenir la signature de fonction par réflexion et doit utiliser l'annotation @Resolve pour la spécifier, par exemple @Resolve("smallint->varchar(10)"). Pour plus d'informations sur l'annotation @Resolve, consultez la section Annotation @Resolve.

  • Implémentation des méthodes dans la classe Java : obligatoire.

    L'implémentation de la classe Java comprend les quatre méthodes suivantes. Implémentez-les selon vos besoins.

    API

    Description

    public void setup(ExecutionContext ctx) throws UDFException

    La méthode d'initialisation. MaxCompute appelle votre logique d'initialisation personnalisée avant que l'UDTF ne commence à traiter les données d'entrée. La méthode setup est appelée une fois par worker.

    public void process(Object[] args) throws UDFException

    La fonction process est appelée une fois pour chaque enregistrement d'une requête SQL. Les paramètres de la fonction process correspondent aux paramètres d'entrée spécifiés pour l'UDTF dans l'instruction SQL. Les paramètres d'entrée sont transmis sous forme de tableau Object[] et la sortie est générée à l'aide de la fonction forward. Vous devez appeler la fonction forward au sein de la fonction process pour déterminer la sortie.

    Remarque

    L'absence d'appel à forward depuis la méthode process ou close peut entraîner une perte de données. Par exemple, si un thread d'arrière-plan exécute un appel forward, vous devez vous assurer que la méthode process ne se termine pas tant que l'appel forward n'est pas terminé afin d'éviter toute perte de données.

    public void close() throws UDFException

    La méthode de terminaison de l'UDTF. Elle n'est appelée qu'une seule fois, après le traitement du dernier enregistrement.

    public void forward(Object …o) throws UDFException

    Appelez la méthode forward pour produire des données ; chaque appel à forward génère un enregistrement. Lorsque vous appelez une UDTF dans une requête SQL, vous pouvez utiliser la clause as pour renommer la sortie de forward.

    Lors de l'écriture d'une UDTF Java, vous pouvez utiliser Java Type ou Java Writable Type. Pour un mappage détaillé entre les types de données pris en charge par MaxCompute et les types de données Java, consultez la section Types de données.

Voici un exemple d'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);
       }
     }
   }

Limitations

  • Accès Internet : par défaut, les UDF ne peuvent pas accéder à Internet. Pour activer l'accès Internet, remplissez le formulaire de demande de connexion réseau. Après approbation, l'équipe d'assistance technique MaxCompute vous contactera pour établir la connexion. Pour plus de détails, consultez la section Processus de connexion réseau.

  • Aucune autre colonne dans le même SELECT : une instruction SELECT qui appelle une UDTF ne peut pas référencer d'autres colonnes ou expressions. L'instruction suivante n'est pas valide :

    -- Invalid: mixes a UDTF with another column
    select value, user_udtf(key) as mycol ...
  • Pas d'imbrication : les UDTF ne peuvent pas être imbriquées dans d'autres UDTF. L'instruction suivante n'est pas valide :

    -- Invalid: user_udtf2 is nested inside user_udtf1
    select user_udtf1(user_udtf2(key)) as mycol...;
  • Incompatible avec GROUP BY, DISTRIBUTE BY et SORT BY : une UDTF ne peut pas apparaître dans la même instruction SELECT que ces clauses. L'instruction suivante n'est pas valide :

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

Considérations

Lorsque vous écrivez une UDTF Java, tenez compte des points suivants :

  • Évitez de définir des classes portant le même nom mais ayant une logique d'implémentation différente dans différents packages JAR UDTF. Par exemple, supposons que UDTF1 et UDTF2 correspondent respectivement aux ressources de package JAR udtf1.jar et udtf2.jar. Si les deux packages JAR contiennent une classe nommée com.aliyun.UserFunction.class avec une logique différente, MaxCompute charge aléatoirement l'une des classes lorsque UDTF1 et UDTF2 sont appelées dans la même instruction SQL. Cela peut entraîner des résultats inattendus ou des échecs de compilation.

  • Les paramètres d'entrée et les valeurs de retour doivent utiliser des types d'objets Java, tels que String et Long, plutôt que des types primitifs.

  • En effet, les valeurs SQL NULL sont transmises en tant que null Java, ce que les types primitifs ne peuvent pas représenter.

Annotation @Resolve

Le format de l'annotation @Resolve est le suivant.

@Resolve(<signature>)

La chaîne signature spécifie les types de données des paramètres d'entrée et des valeurs de retour de l'UDTF. Lors de l'analyse de la requête, MaxCompute valide les appels par rapport à cette signature et signale une erreur en cas d'incompatibilité de type. Le format est le suivant.

'arg_type_list -> type_list'

Où :

  • type_list : représente les types de données des valeurs de retour. Une UDTF peut renvoyer plusieurs colonnes. Les types de données pris en charge sont BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(precision,scale), les types de données complexes (ARRAY, MAP, STRUCT) et les types de données complexes imbriqués.

  • arg_type_list : représente les types de données des paramètres d'entrée. Plusieurs paramètres d'entrée peuvent être spécifiés, séparés par des virgules (,). Les types de données pris en charge sont BIGINT, STRING, DOUBLE, BOOLEAN, DATETIME, DECIMAL, FLOAT, BINARY, DATE, DECIMAL(precision,scale), CHAR, VARCHAR, les types de données complexes (ARRAY, MAP, STRUCT) et les types de données complexes imbriqués.

    La arg_type_list prend également en charge un astérisque (*) ou une chaîne vide ('').

    • Si la arg_type_list est un astérisque (*), cela indique que la fonction accepte n'importe quel nombre de paramètres d'entrée.

    • Si la arg_type_list est une chaîne vide (''), cela indique que la fonction n'a aucun paramètre d'entrée.

    Pour plus d'informations sur la syntaxe étendue de l'annotation Resolve, consultez la section Paramètres dynamiques pour les UDAF et les UDTF.

Le tableau suivant présente des exemples d'annotations @Resolve valides.

Exemple

Description

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

Les types de paramètres d'entrée sont BIGINT et BOOLEAN. Les types de valeurs de retour sont STRING et DATETIME.

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

La fonction accepte n'importe quel nombre de paramètres d'entrée. Les types de valeurs de retour sont STRING et DATETIME.

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

La fonction n'a aucun paramètre d'entrée. Les types de valeurs de retour sont DOUBLE, BIGINT et STRING.

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

Les types de paramètres d'entrée sont ARRAY, STRUCT et STRING. Les types de valeurs de retour sont MAP et STRUCT.

Types de données

Les types de données pris en charge par MaxCompute varient selon l'édition du type de données. À partir de MaxCompute 2.0, des types de données supplémentaires sont disponibles, notamment des types complexes tels que ARRAY, MAP et STRUCT. Pour plus d'informations, consultez la section Éditions des types de données.

Lors de l'écriture d'une UDTF Java, assurez-vous que les types de données que vous utilisez correspondent correctement à ceux pris en charge par MaxCompute. Le tableau suivant décrit ces mappages.

Type MaxCompute

Type Java

Type 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

Remarque

Pour utiliser les types Java Writable pour les entrées ou les valeurs de retour de l'UDTF, votre projet MaxCompute doit utiliser l'édition de type de données MaxCompute 2.0.

Utilisation

Après avoir développé une UDTF Java en suivant le processus de développement, vous pouvez l'appeler dans MaxCompute SQL.

  • Utilisation d'une UDF dans un projet MaxCompute : la méthode est similaire à celle de l'utilisation des fonctions intégrées. Vous pouvez utiliser une fonction définie par l'utilisateur de la même manière qu'une fonction intégrée.

  • Utilisation d'une UDF entre projets : utilisez une UDF du projet B dans le projet A. L'instruction suivante montre un exemple : select B:udf_in_other_project(arg0, arg1) as res from table_t;. Pour plus d'informations sur le partage interprojets, consultez la section Accès aux ressources interprojets basé sur les packages.

Pour une procédure complète de développement et d'appel d'une UDTF Java à l'aide de MaxCompute Studio, consultez la section Exemple d'utilisation.

Exemple d'utilisation

La procédure suivante vous guide pas à pas dans le développement et l'appel d'une UDTF Java à l'aide de MaxCompute Studio :

  1. Préparez l'environnement.

    Avant de pouvoir développer et déboguer une UDF dans MaxCompute Studio, installez MaxCompute Studio et connectez-le à un projet MaxCompute. Pour plus d'informations, consultez les rubriques suivantes :

    1. Installer MaxCompute Studio

    2. Se connecter à un projet MaxCompute

    3. Créer un module Java MaxCompute

  2. Écrivez le code UDTF.

    1. Dans l'explorateur Project, cliquez avec le bouton droit sur le répertoire source du module (src > main > java) et sélectionnez New > MaxCompute Java.

    2. Dans la boîte de dialogue Create new MaxCompute java class, cliquez sur UDTF, saisissez un Name et appuyez sur Entrée. Par exemple, nommez la classe Java MyUDTF.

      Name correspond au nom de la classe Java MaxCompute à créer. Si aucun package n'a été créé, vous pouvez saisir ici packagename.classname pour générer automatiquement un package.

    3. Dans l'éditeur de code, saisissez le code suivant. Il s'agit d'un exemple de code 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. Exécutez et déboguez l'UDTF localement pour vous assurer que le code fonctionne comme prévu.

    Pour plus d'informations sur le débogage, consultez la section Exécuter et déboguer une UDF localement.

    Cliquez avec le bouton droit sur le fichier MyUDTF dans l'arborescence du projet et sélectionnez Run 'MyUDTF.main()'. Dans la boîte de dialogue Run/Debug Configurations, définissez MaxCompute project sur local, MaxCompute table sur wc_in2, Table partition sur p2=1,p1=2, Table columns sur colc,colb, Download Record limit sur 100 et Data Column Separator sur |. Cliquez ensuite sur OK.

    Remarque

    Vous pouvez utiliser les paramètres précédents pour l'exécution de l'exemple.

  4. Empaquetez l'UDTF dans un package JAR, téléchargez-le dans votre projet MaxCompute et enregistrez la fonction. Pour cet exemple, nommez la fonction user_udtf.

    Pour plus d'informations sur l'empaquetage, consultez la section Procédure.

    Dans l'arborescence du projet IntelliJ IDEA, cliquez avec le bouton droit sur le fichier Java UDTF (par exemple, MyUDTF) et sélectionnez Deploy to server.... Dans la boîte de dialogue Package a jar, submit resource and register function, sélectionnez le MaxCompute project cible, confirmez le chemin d'accès au Resource file, définissez Main class sur la classe UDTF correspondante (par exemple, org.alidata.odps.udtf.examples.MyUDTF), saisissez user_udtf pour Function name, sélectionnez Force update if already exists et cliquez sur OK pour terminer le déploiement.

  5. Dans le volet de navigation de gauche de MaxCompute Studio, cliquez sur Project Explorer. Cliquez avec le bouton droit sur le projet MaxCompute cible, démarrez le client MaxCompute et exécutez une commande SQL pour appeler l'UDTF nouvellement créée.

    Supposons que la table cible, my_table, contienne les données suivantes :

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

    Exécutez la commande SQL suivante pour appeler l'UDTF.

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

    Le résultat suivant est renvoyé.

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

Documentation connexe

Pour plus d'exemples d'utilisation des UDTF Java, consultez la section Exemples de UDTF Java.