使用反射将pojo写入镶木地板文件

时间:2014-10-18 00:53:49

标签: apache hadoop serialization avro parquet

HI寻找使用Pojos编写parquest的API。 我能够使用反射生成avro模式,然后使用AvroSchemaConverter创建镶木地板模式。 此外,我无法找到将Pojos转换为GenericRecords(avro)的方法,否则我本可以使用AvroParquetWriter将Pojos写入镶木地板文件。 有什么建议吗?

3 个答案:

答案 0 :(得分:1)

如果您想通过avro,您有两种选择:

1)让avro生成你的pojos(参见教程here)。生成的pojos扩展了SpecificRecord,然后可以与AvroParquetWriter一起使用。

2)自己编写从pojo到GenericRecord的转换。您可以手动执行此操作,也可以使用更通用的解决方案。但是,当我尝试读取数据时,我遇到了这种方法的困难。基于提供的模式,avro在类路径中找到了pojo,并尝试实例化一个SpecificRecord而不是GenericRecord。由于这个原因,我选择了选项1.

Parquet也支持现在直接写pojo。 Here是镶木地板github页面上的拉取请求。但是,我认为这还不是官方发布的一部分。换句话说,我没有在maven中找到这段代码。

答案 1 :(得分:0)

免责声明:以下代码是在我赶时间写的。它效率不高,未来版本的镶木地板肯定会更直接地解决这个问题。话虽如此,这是一种轻量级的低效方法,可满足您的需求。策略是POJO - > AVRO - > PARQUET

  1. POJO - > AVRO:通过反射声明一个模式。根据模式声明编写者和读者。在转换时将对象写入字节流并将其作为avro。
  2. 读回
  3. AVRO - >实木复合地板:使用镶木地板项目中包含的AvroParquetWriter。

  4. private static final Schema avroSchema = ReflectData.AllowNull.get().getSchema(YOURCLASS.class);
    private static final ReflectDatumWriter<YOURCLASS> reflectDatumWriter = new ReflectDatumWriter<>(avroSchema);
    private static final GenericDatumReader<Object> genericRecordReader = new GenericDatumReader<>(avroSchema);
    
    public GenericRecord toAvroGenericRecord() throws IOException {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        reflectDatumWriter.write(this, EncoderFactory.get().directBinaryEncoder(bytes, null));
        return (GenericRecord) genericRecordReader.read(null, DecoderFactory.get().binaryDecoder(bytes.toByteArray(), null));
    }
    

    还有一件事:看来镶木地板作家目前对空领域非常严格。在尝试写入镶木地板

    之前,请确保没有任何字段为空

答案 2 :(得分:0)

我无法找到现有的解决方案,所以我自己实现了。以下是实施的链接:https://gist.github.com/alexeygrigorev/eab72e40c6051e0163a6693054906d66

简而言之,它执行以下操作:

  • 使用反射从pojo
  • 获取Avro架构
  • 使用架构和反射将pojos转换为GenericRecord个对象
  • 如果pojo包含其他pojos或pojos列表,则递归应用
  • 反射