【问题标题】:Write pojo's to parquet file using reflection使用反射将 pojo 写入镶木地板文件
【发布时间】:2014-12-13 15:27:13
【问题描述】:

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

【问题讨论】:

    标签: apache hadoop serialization avro parquet


    【解决方案1】:

    如果你想通过 avro,你有两个选择:

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

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

    Parquet 现在也支持直接写 pojo。 Here 是 parquet github 页面上的拉取请求。但是,我认为这还不是正式版本的一部分。也就是说,我在maven中没有找到这段代码。

    【讨论】:

    • 感谢 Karolovbrat 的建议。我会试试这些。理想情况下,我希望看到发布的拉取请求。我看到 Parquet 版本 2.x 即将发布
    • 您可以执行以下操作来修复@karolovbrat 声明的阅读器问题 Configuration conf = new Configuration(); conf.set(AVRO_DATA_SUPPLIER, GenericDataSupplier.class.getName()); ParquetReader parquetReader = AvroParquetReader.builder(new Path(this.file.getAbsolutePath())) .withConf(conf) .build();
    【解决方案2】:

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

    1. POJO -> AVRO:通过反射声明模式。根据模式声明作者和读者。在转换时将对象写入字节流并将其作为 avro 读回。
    2. AVRO -> Parquet:使用 parquet-me 项目中包含的 AvroParquetWriter。

    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));
    }
    

    还有一件事:parquet writer 目前似乎对 null 字段非常严格。在尝试写入 parquet 之前,请确保您的所有字段都不为空

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2021-10-28
        • 2019-06-02
        • 1970-01-01
        • 1970-01-01
        • 2020-04-22
        • 2021-03-15
        • 1970-01-01
        • 2021-08-27
        • 1970-01-01
        相关资源
        最近更新 更多