Avro 1.11.1:创建多精度Scale的Decimal类型Schema报错求助
错误原因与解决方案
错误原因
Avro的Schema对象是不可变的,当你为一个bytes类型的Schema添加decimal逻辑类型的precision和scale属性后,这些属性就永久绑定到该Schema实例上,无法再修改。如果尝试复用同一个Schema实例,给第二个decimal字段设置不同的scale或precision,就会触发AvroRuntimeException——因为Avro不允许覆盖已存在的Schema属性。
解决方法
为每个拥有不同精度/小数位的decimal字段创建独立的Schema实例,不要复用同一个基础Schema对象修改属性。推荐使用Avro提供的SchemaBuilder来构建,代码更简洁且不易出错:
示例代码
import org.apache.avro.Schema; import org.apache.avro.SchemaBuilder; public class AvroDecimalExample { public static void main(String[] args) { // 为salary1创建独立的decimal Schema Schema salary1Schema = SchemaBuilder.builder() .bytesType() .prop("logicalType", "decimal") .prop("precision", 30) .prop("scale", 10); // 为salary2创建独立的decimal Schema Schema salary2Schema = SchemaBuilder.builder() .bytesType() .prop("logicalType", "decimal") .prop("precision", 20) .prop("scale", 8); // 构建包含两个decimal字段的Record Schema Schema employeeSchema = SchemaBuilder.record("Employee") .namespace("com.example") .fields() .name("salary1").type(salary1Schema).noDefault() .name("salary2").type(salary2Schema).noDefault() .endRecord(); // 打印验证Schema结构 System.out.println(employeeSchema.toString(true)); } }
手动创建Schema实例(不使用SchemaBuilder)
如果习惯手动创建,也可以为每个decimal字段单独生成bytes类型的Schema,再添加逻辑类型属性:
Schema salary1Schema = Schema.create(Schema.Type.BYTES); salary1Schema.addProp("logicalType", "decimal"); salary1Schema.addProp("precision", 30); salary1Schema.addProp("scale", 10); Schema salary2Schema = Schema.create(Schema.Type.BYTES); salary2Schema.addProp("logicalType", "decimal"); salary2Schema.addProp("precision", 20); salary2Schema.addProp("scale", 8);
关键注意点
- Avro 1.11.1中,逻辑类型的属性是Schema实例的固有部分,一旦设置就无法修改,必须为每个参数不同的decimal字段创建新的Schema。
- 使用
SchemaBuilder是Avro官方推荐的方式,它能确保Schema的不可变性被正确处理,避免手动修改属性带来的异常。
内容的提问来源于stack exchange,提问作者MarianS
相关产品推荐
相关产品推荐

