基本クラスを拡張するか、インターフェースを実装するJavaクラスを生成するAvroスキーマ/ IDLを作成することは可能ですか?生成されたJava =クラスはorg.Apache.avro.specific.SpecificRecordBase
を拡張します。したがって、実装が進むべき道かもしれませんが、これが可能かどうかはわかりません。
継承セマンティクスよりも多くの関連付けを使用して、特定のスキーマごとに明示的な「タイプ」フィールドを定義する提案のある例を見てきました。
基本クラスは、ファクトリクラスや、コードの他の部分で<T extends BaseObject>
などのジェネリックを使用して頻繁に使用しています。現在、継承をサポートするJSONスキーマからコードを生成しました。
別の副次的な質問:IDLを使用して、プロトコル定義なしでレコードのみを定義できますか?コンパイラがprotocolキーワードの欠落について文句を言うので、答えはノーだと思います。
感謝します!ありがとう。
私はこの問題を解決するためのより良い方法を見つけました。 Avroのスキーマ生成ソースを見ると、内部的にクラス生成ロジックがVelocityスキーマを使用してクラスを生成していることがわかりました。
record.vm
テンプレートを変更して、特定のインターフェイスも実装しました。 MavenビルドプラグインのtemplateDirectory
構成を使用して、velocityディレクトリの場所を指定する方法があります。
また、SpecificDatumWriter
の代わりに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>
この質問にも同様の問題があることがわかりました。私の場合、マーカーインターフェイスを課すだけで、一部タイプにのみ課す必要がありました(後で特定のクラスを区別するため)。あなたの答えのおかげで、私はrecord.vm
テンプレートの構造を深く掘り下げました。 "javaAnnotation": "my.full.AnnotationName"
定義JSONで.avsc
キーを定義できることがわかりました。次に、@my.full.AnnotationName
が生成されたクラスに追加されます。
確かに、このソリューションは最終的にマーカーインターフェイス上に構築されていませんが、私の目的には十分であり、テンプレートをそのままにしておくことは大きな利点です。
ReflectData
APIを使用して実行時にクラスからスキーマを生成し、次にReflectDatumWriter
をシリアル化に使用することにしました。反射の使用は遅くなります。ただし、スキーマは内部にキャッシュされているようです。パフォーマンスの問題が発生した場合は、報告します。
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
}