我正在编写一些将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),我假设我只能检测Field为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。
我在这里缺少什么?是否可以使AVRO字段是可选的LONG?
我考虑过不编写TSV文件而只是直接从我在ResultSet中看到的编写AVRO文件,但我有预感我会遇到同样的问题,因为DataFileWriter似乎没有喜欢“”或LONG字段的空值。我想我可以把所有东西都变成一个STRING字段,但是我更喜欢保留列类型,以便排序,以及在下游正常工作。