Class RowWriter

java.lang.Object
dev.hardwood.writer.RowWriter

@Experimental public final class RowWriter extends Object

Writes a Parquet file record by record, over the same columnar core ColumnWriter exposes through ColumnWriter.writeBatch(Consumer).

This is the write-side mirror of the reader's rowReader(): the ergonomic API for a caller that holds records rather than columns. Fields are addressed by the name they carry in the schema, nesting is entered with a filler per level, and logical-type values are written as the Java types the reader returns for them.

try (ParquetFileWriter writer = ParquetFileWriter.create(out, schema)) {
    RowWriter rows = writer.rowWriter();
    for (Person person : people) {
        rows.writeRow(row -> row
                .setLong("id", person.id())
                .setString("name", person.name())
                .setDate("hired", person.hired())
                .setStruct("address", address -> address.setString("city", person.city()))
                .setList("phones", phones -> person.phones().forEach(phones::addString)));
    }
}

Records are staged into a batch and submitted through the columnar path, so paging, row group cadence, dictionary encoding, compression and statistics are exactly those of a file written through ColumnWriter.writeBatch(Consumer). A batch is submitted once it holds enough records, or once its variable-width payload reaches the configured row-group size, so staging never exceeds one row group regardless of how large the values are.

A RowWriter is not closeable: the ParquetFileWriter it came from owns the file, and closing it writes the records still staged here along with the footer.

This API is Experimental: the shape may change in future releases.

  • Method Details

    • writeRow

      public void writeRow(Consumer<StructBuilder> filler) throws IOException

      Writes one record.

      The writer creates the builder — bound to the schema — passes it to filler to be populated, then stages the record. A field the filler leaves unset is written as null if it is OPTIONAL, and fails the record if it is REQUIRED.

      A record that fails is staged in full or not at all: if the filler rejects a value or throws, everything it staged is discarded and the writer is left exactly as it was before the call, so the caller can handle the failure and carry on with the next record.

      Parameters:
      filler - populates the record
      Throws:
      IOException - if writing a completed batch fails
      IllegalArgumentException - if the filler names a field the schema does not have, sets one twice, uses a setter that does not fit a field's declared type, or leaves a REQUIRED field unset
      IndexOutOfBoundsException - if the filler addresses a field by an index the struct it is setting does not have
      IllegalStateException - if the writer is closed