Polymorphisme et hérédité dans les schèmes Avro

est-il possible d'écrire un Avro schema/IDL qui générera une classe Java qui étend une classe de base ou implémente une interface? Il semble que la classe Java générée étend le org.apache.avro.specific.SpecificRecordBase. Donc, les instruments pourraient être la voie à suivre. Mais, je ne sais pas si c'est possible.

j'ai vu des exemples avec des suggestions pour définir un champ "type" explicite dans chaque schéma spécifique, avec plus d'une association que la sémantique de l'héritage.

j'utilise ma classe de base lourdement dans mes classes d'usine et d'autres parties du code avec des génériques comme <T extends BaseObject>. Actuellement, j'ai fait générer du code informatique à partir du schéma JSON, qui supporte l'héritage.

autre question secondaire: pouvez-vous utiliser IDL pour définir juste des enregistrements sans la définition du protocole? Je pense que la réponse est non parce que le compilateur se plaint du mot-clé de protocole manquant.

Aide appréciée! Grâce.

19
demandé sur Kirby 2014-01-01 04:14:35

2 réponses

j'ai trouvé un meilleur moyen de résoudre ce problème. En regardant la source de génération de schéma dans Avro, j'ai compris qu'à l'interne la logique de génération de classe utilise des schémas de vitesse pour générer les classes.

j'ai modifié le record.vm modèle pour aussi mettre en oeuvre mon interface spécifique. Il y a un moyen de spécifier l'emplacement du répertoire velocity en utilisant le templateDirectory configuration dans le plugin Maven build.

j'ai également passé à l'aide de SpecificDatumWriter au lieu de reflectDatumWriter.

<plugin>
  <groupId>org.apache.avro</groupId>
  <artifactId>avro-maven-plugin</artifactId>
   <version>${avro.version}</version>
   <executions>
    <execution>
      <phase>generate-sources</phase>
      <goals>
        <goal>schema</goal>
      </goals>
      <configuration>
         <sourceDirectory>${basedir}/src/main/resources/avro/schema</sourceDirectory>
         <outputDirectory>${basedir}/target/java-gen</outputDirectory>
         <fieldVisibility>private</fieldVisibility>
         <stringType>String</stringType>
         <templateDirectory>${basedir}/src/main/resources/avro/velocity-templates/</templateDirectory>
       </configuration>
    </execution>
  </executions>
</plugin>
13
répondu bsam 2016-06-15 22:21:40

j'ai décidé d'utiliser le ReflectData API pour générer le schéma à partir de la classe à l'exécution et ensuite utiliser le ReflectDatumWriter pour la sérialisation. L'utilisation de la réflexion sera plus lent. Mais, on dirait que le schéma est caché en interne. Je ferai rapport si je vois des problèmes de performance.

Schema schema = ReflectData.AllowNull.get().getSchema(sourceObject.getClass());
ReflectDatumWriter<T> reflectDatumWriter = new ReflectDatumWriter<>(schema);

DataFileWriter<T> writer = new DataFileWriter<>(reflectDatumWriter);
try {
    writer.setCodec(CodecFactory.snappyCodec());
    writer.create(schema, new File("data.avro"));
    writer.append(sourceObject);
    writer.close();
}
catch (IOException e) {
    // log exception
}
1
répondu bsam 2016-06-15 22:22:13