2

我正在编写一些将 Java ResultSet 存储为 AVRO 数据/模式的代码。我对 AVRO 很陌生。

我这样做的方式是获取 ResultSet 并查询其 ColumnMetadata 以生成 AVRO 模式。在这里,我从 Oracle 类型转换为 AVRO 类型。例如,我将 VARCHAR 转换为 STRING,将 NUMBER 转换为 LONG。

然后,我从 ResultSet 中获取数据并将其写为 TSV 文件,这样我们就有了一个人类可读的输出版本,用于诊断目的。然后我遍历 TSV 文件中的内容,并使用 DatumWriter/DataFileWriter 将其写为 AVRO 文件。

我遇到的问题是我正在查询的一些(Oracle)表具有可为空的 NUMBER 列。在此列为空的情况下,当我从 TSV 文件中读取它时,它是“”。如果我尝试将 "" 写入 LONG 字段,DataFileWriter 会因以下异常而窒息:

Exception in thread "main" org.apache.avro.file.DataFileWriter$AppendWriteException: java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Long

由于此处的消息表明 DataFileWriter 正在使用 java.lang.Long(而不是原始 long),我假设我可以检测字段为 LONG 且值为“”的情况,并将值显式设置为 null .

当我尝试序列化它时,我得到以下异常:

Exception in thread "main" org.apache.avro.file.DataFileWriter$AppendWriteException: java.lang.NullPointerException: null of long in field COLUMN_NAME of NAMESPACE.NAME

现在这个异常是指原始 long 而不是 java.lang.Long。

我在这里想念什么?是否可以有一个可选 LONG 的 AVRO 字段?

我考虑过不编写 TSV 文件,而是直接从我在 ResultSet 中看到的内容编写 AVRO 文件,但我有预感我会遇到同样的问题,因为 DataFileWriter 似乎不喜欢“”或 LONG 字段的空值。我想我可以将所有内容都设为 STRING 字段,但我更愿意保留列类型,以便排序和下游正常工作。

4

0 回答 0