Flink中Avro Date逻辑类型写入Parquet时ClassCast异常求助
解决Flink中Avro Date逻辑类型写入Parquet的ClassCast异常
问题根源
Avro 1.11.1的date逻辑类型底层基于int存储,实际值是从1970-01-01(Epoch)开始计算的天数。你直接给Avro对象设置LocalDate实例,Parquet序列化器会尝试将其强制转换为Number类型,从而触发ClassCast异常。
解决方案
核心是把LocalDate转换为Avro Date逻辑类型对应的int天数,再写入Avro对象:
1. 转换LocalDate为int天数
使用ChronoUnit.DAYS计算目标日期到Epoch的天数差,将结果作为int值传入Avro对象:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d/MM/yyyy"); String date = "16/08/2016"; LocalDate localDate = LocalDate.parse(date, formatter); // 计算从1970-01-01到目标日期的天数 int daysSinceEpoch = (int) ChronoUnit.DAYS.between(LocalDate.ofEpochDay(0), localDate); myAvroObject.setDate(daysSinceEpoch);
2. 读取时转回LocalDate(可选)
如果后续需要读取Parquet中的Date字段,可将存储的int值转回LocalDate:
int daysSinceEpoch = (int) genericRecord.get("Date"); LocalDate localDate = LocalDate.ofEpochDay(daysSinceEpoch);
3. 确认Avro代码生成配置(若使用代码生成工具)
如果通过Avro Maven插件生成Java类,需确保插件启用逻辑类型支持,避免生成的代码不兼容逻辑类型:
<plugin> <groupId>org.apache.avro</groupId> <artifactId>avro-maven-plugin</artifactId> <version>1.11.1</version> <executions> <execution> <phase>generate-sources</phase> <goals> <goal>schema</goal> </goals> <configuration> <stringType>String</stringType> <enableDecimalLogicalType>true</enableDecimalLogicalType> </configuration> </execution> </executions> </plugin>
补充说明
之前直接用int保存正常,是因为int类型完全匹配Avro Date逻辑类型的底层存储格式,序列化器无需额外转换;而传入LocalDate时,序列化器无法自动完成类型映射,因此抛出转换异常。
内容的提问来源于stack exchange,提问作者Saurabh Rana
相关产品推荐
相关产品推荐

