Avro模式中的多态性和继承

bsa*_*sam 23 avro

是否可以编写一个Avro架构/ IDL来生成扩展基类或实现接口的Java类?似乎生成的Java类扩展了org.apache.avro.specific.SpecificRecordBase.因此,工具可能是要走的路.但是,我不知道这是否可行.

我已经看到了一些示例,其中提出了在每个特定模式中定义显式"类型"字段的建议,其中包含的关联多于继承语义.

我在我的工厂类和代码的其他部分中大量使用我的基类<T extends BaseObject>.目前,我有从JSON Schema生成的代码,它支持继承.

另一个问题是:你可以使用IDL来定义没有协议定义的记录吗?我认为答案是否定的,因为编译器抱怨缺少协议关键字.

帮助赞赏!谢谢.

bsa*_*sam 15

我找到了解决这个问题的更好方法.看一下Avro中的Schema生成源,我发现在类内部,类生成逻辑使用Velocity模式来生成类.

我修改了record.vm模板以实现我的特定接口.有一种方法可以使用templateDirectorymaven构建插件中的配置指定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>
Run Code Online (Sandbox Code Playgroud)

  • 仍然在模式级别寻找一些继承解决方案(非常确定没有),但我很高兴你记录了自己的发现.谢谢! (2认同)

小智 5

如果我在这里写下我已经为这种情况创建了 Maven 插件,我希望对其他人有所帮助 - https://github.com/tunguski/interfacer

它会遍历自动生成的类,并检查它们是否符合特定包中类路径上找到的接口。如果是,则将接口添加到类中。它适用于通用接口,至少在我必须处理的基本示例中是这样。

该插件不是 avro 特定的,它用作生成的代码后处理器,因此它也可以在其他情况下使用。

<!-- 
  post process avro generated sources and add interfaces from package
  pl.matsuo.interfacer.showcase to every generated class that has 
  all methods from specific interface
 -->
<plugin>
    <groupId>pl.matsuo.interfacer</groupId>
    <artifactId>interfacer-maven-plugin</artifactId>
    <version>0.0.6</version>
    <executions>
        <execution>
            <configuration>
                <interfacesDirectory>${project.basedir}/src/main/java</interfacesDirectory>
                <interfacePackage>pl.matsuo.interfacer.showcase</interfacePackage>
            </configuration>
            <goals>
                <goal>add-interfaces</goal>
            </goals>
        </execution>
    </executions>
</plugin>
Run Code Online (Sandbox Code Playgroud)
// src/main/java manually defined interface
public interface HasName {
  String getName();
}

// target/generated-sources/avro
public class Person {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}

public class Company {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}

// after this plugin run

// target/generated-sources/avro
public class Person implements HasName {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}

public class Company implements HasName {

  String name;

  public String getName() {
    return name;
  }
  // [...]
}
Run Code Online (Sandbox Code Playgroud)