Java ApacheAvro如何序列化(大型)数据结构

Java ApacheAvro如何序列化(大型)数据结构,java,code-generation,avro,Java,Code Generation,Avro,我正在考虑在hadoop上使用AVRO。但我关心的是大型数据结构的序列化以及如何向(数据)类添加方法 示例(取自)显示了facebook用户的模型 { "namespace": "test.avro", "name": "FacebookUser", "type": "record", "fields": [ {"name": "name", "type": "string"}, ..., {"name": "friends", "type":

我正在考虑在hadoop上使用AVRO。但我关心的是大型数据结构的序列化以及如何向(数据)类添加方法

示例(取自)显示了facebook用户的模型

{
  "namespace": "test.avro",
  "name": "FacebookUser",
  "type": "record",
  "fields": [
      {"name": "name", "type": "string"},
      ...,
      {"name": "friends", "type": "array", "items": "FacebookUser"} 
  ]
}
avro是否序列化此模型中FaceBook用户的完整社交图?

[也就是说,如果我想序列化一个用户,那么序列化是否包括它的所有好友及其好友等?]

如果答案是肯定的,我宁愿存储朋友的ID而不是参考资料,以便在需要时在应用程序中查找。在这种情况下,我希望能够添加一个返回实际好友而不是ID的方法

如何包装/扩展生成的AVRO java类以添加方法?


(也可以添加返回例如friend count的方法)

我试图首先回答第一个问题:
据我所知,AVRO并不是为了存储非层次化的东西而构建的。它也没有对象ID的表示法。它可以存储数组、基元类型的记录或它们的任意组合。您所指的对象图形的传输能力是Java序列化的能力,而AVRO lacing的能力
因此,为了存储一些图形,您应该引入自己的对象ID,并明确地将它们分配给一些字段。 您可以在此处查看getSchema方法: 这相当简单。。。这是AVRO通过java类生成模式的一种方式

关于第二个问题,我认为修改生成的代码不是一个好主意。我建议用您想要添加的所有方法/数据创建一个类,并将AVRO生成的“数据”类作为其中的一个成员
同时,我认为从技术上扩展生成的类应该是可以的。

关于第二个问题:如何包装/扩展生成的AVRO java类以添加方法?

可以使用AspectJ将新方法注入到现有/生成的类中。AspectJ只在编译时需要。该方法如下所示

将个人记录定义为Avro IDL(Person.avdl):

使用maven和从AVDL生成java源代码:

<dependency>
    <groupId>org.apache.avro</groupId>
    <artifactId>avro</artifactId>
    <version>1.6.3</version>
</dependency>
    ......
    <plugin>
        <groupId>org.apache.avro</groupId>
        <artifactId>avro-maven-plugin</artifactId>
        <version>1.6.3</version>
        <executions>
            <execution>
                <id>generate-avro-sources</id>
                <phase>generate-sources</phase>
                <goals>
                    <goal>idl-protocol</goal>
                </goals>
                <configuration>
                    <sourceDirectory>src/main/resources/avro</sourceDirectory>
                    <outputDirectory>${project.build.directory}/generated-sources/java</outputDirectory>
                </configuration>
            </execution>
        </executions>
    </plugin>
使用maven插件将此方面与生成的代码结合起来

<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.6.12</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.6.12</version>
</dependency>
    ....
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.2</version>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.6.12</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <source>6</source>
        <target>6</target>
    </configuration>
</plugin>

超越试图用AVRO解决这些问题,这可能是不可行的(我猜想,扩展生成的类不会很好地工作,不管你怎么尝试),你可以考虑使用普通JSON(除非你对AVRO有特定的要求)。 许多库支持任意POJO映射;还有一些(比如)还支持基于对象Id的序列化(使用2.0.0)

package net.tzolov.avro.extend;

import net.tzolov.avro.extend.Person;

public aspect PersonAspect {

    public String Person.getCompleteName() {        
        return this.getFirstName() + " " + this.getLastName();
    }
}
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjrt</artifactId>
    <version>1.6.12</version>
</dependency>
<dependency>
    <groupId>org.aspectj</groupId>
    <artifactId>aspectjweaver</artifactId>
    <version>1.6.12</version>
</dependency>
    ....
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>aspectj-maven-plugin</artifactId>
    <version>1.2</version>
    <dependencies>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>1.6.12</version>
        </dependency>
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjtools</artifactId>
            <version>1.6.12</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <goals>
                <goal>compile</goal>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <source>6</source>
        <target>6</target>
    </configuration>
</plugin>
@Test
public void testPersonCompleteName() throws Exception {

    Person person = Person.newBuilder()
            .setFirstName("John").setLastName("Atanasoff").build();

    Assert.assertEquals("John Atanasoff", person.getCompleteName());
}