4

私はhadoopでAVROを使用することを検討しています。しかし、私は大きなデータ構造のシリアル化と(data-)クラスにメソッドを追加する方法に関心があります。

この例(http://blog.voidsearch.com/bigdata/apache-avro-in-practice/から取得)は、Facebookユーザーのモデルを示しています。

{
  "namespace": "test.avro",
  "name": "FacebookUser",
  "type": "record",
  "fields": [
      {"name": "name", "type": "string"},
      ...,
      {"name": "friends", "type": "array", "items": "FacebookUser"} 
  ]
}

avroは、このモデルでfacebookuserの完全なソーシャルグラフをシリアル化しますか?

[つまり、1人のユーザーをシリアル化する場合、シリアル化にはそのすべての友人とその友人などが含まれますか?]

答えが「はい」の場合、必要なときにいつでもアプリケーションで検索できるように、参照ではなく友人のIDを保存したいと思います。その場合、IDの代わりに実際の友達を返すメソッドを追加できるようにしたいと思います。

生成されたAVROJavaクラスをラップ/拡張してメソッドを追加するにはどうすればよいですか?

(たとえば、friend-countを返すメソッドを追加するためにも)

4

3 に答える 3

3

2番目の質問について:生成されたAVRO Javaクラスをラップ/拡張してメソッドを追加するにはどうすればよいですか?

AspectJを使用して、既存の/生成されたクラスに新しいメソッドを挿入できます。AspectJはコンパイル時にのみ必要です。アプローチを以下に示します。

PersonレコードをAvroIDL(person.avdl)として定義します。

@namespace("net.tzolov.avro.extend")
protocol PersonProtocol {
    record Person {
        string firstName;
        string lastName;
    }     
}

mavenとavro-maven-pluginを使用して、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>

上記の構成は、person.avidファイルがsrc / main / resources/avroにあることを前提としています。ソースはtarget/generated-sources/javaで生成されます。

生成されたPerson.javaには、getFirstName()とgetLastName()の2つのメソッドがあります。getCompleteName() = firstName + lastNameという別のメソッドで拡張する場合は、次の側面でこのメソッドを挿入できます。

package net.tzolov.avro.extend;

import net.tzolov.avro.extend.Person;

public aspect PersonAspect {

    public String Person.getCompleteName() {        
        return this.getFirstName() + " " + this.getLastName();
    }
}

生成されたコードでこのアスペクトを織り込むには、aspectj-maven-pluginmavenプラグインを使用します

<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());
}
于 2012-03-28T22:20:28.690 に答える
2

私は最初の質問に最初に答えようとし
ています。私の理解では、AVROは階層的でないものを格納するようには構築されていません。また、オブジェクトIDの表記もありません。配列、プリミティブ型のレコード、またはそれらの任意の組み合わせを格納できます。参照するオブジェクトのグラフをトラバースする機能は、AVROレーシングを使用したJavaシリアル化の機能です。
したがって、グラフを保存するには、独自のオブジェクトIDを導入し、それらをいくつかのフィールドに明示的に割り当てる必要があります。ここでgetSchemaメソッドを調べることができます:http ://www.java2s.com/Open-Source/Java/Database-DBMS/hadoop-0.20.1/org/apache/avro/reflect/ReflectData.java.htm itかなり単純です...これは、AVROがJavaクラスによってスキーマを生成する方法です。
2番目の質問について-生成されたコードを変更するのは良い考えではないと思います。追加したいすべてのメソッド/データでクラスを作成し、そこにAVROで生成された「データ」クラスをメンバーとして配置することをお勧めします。
同時に、生成されたクラスを技術的に拡張することは問題ないと思います。

于 2012-03-27T21:21:01.397 に答える
0

Avroでこれらの問題を解決しようとする以外に(Avroに特定の要件がない限り)、生成されたクラスの拡張はどのように試してもうまく機能しないと思います)。多くのライブラリは任意のPOJOマッピングをサポートしています。また、一部(Jacksonなど)は、オブジェクトIDベースのシリアル化(2.0.0を使用)もサポートしています。

于 2012-04-24T05:33:18.897 に答える