Flink Table创建数组类型字段报ValidationException类型不匹配如何解决
Flink SQL创建包含ARRAY类型字段临时表类型不匹配解决方案
问题根因
- 代码笔误:DataStream变量定义名为
dataStream,但调用tableEnv.fromDataStream()时传入了不存在的dataStreamMap变量,首先会触发运行时错误。 - POJO类不符合规范:自定义
Order类未提供无参构造方法、对应属性的getter/setter方法,Flink无法正确提取字段元数据,导致类型校验失败。 - 字段类型不匹配:
Order类中amount属性为Integer类型,对应Flink SQL的INT类型,但建表语句中将amount定义为BIGINT,类型不一致触发ValidationException。 - 执行逻辑冲突:
tableEnv.executeSql()执行INSERT语句已经会触发作业提交,后续再调用env.execute()会导致作业重复提交异常。 - 空的WITH配置:建表语句中WITH参数为空,实际运行时需要补充对应sink(此处为ClickHouse)的连接器配置才能正常运行。
修正后代码
import org.apache.flink.streaming.api.datastream.DataStream; import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment; import org.apache.flink.table.api.Table; import org.apache.flink.table.api.bridge.java.StreamTableEnvironment; import java.util.Arrays; import java.util.List; import static org.apache.flink.table.api.Expressions.$; public class FlinkConnectorClickhouse { public static void main(String[] args) throws Exception { // 创建执行环境 StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment(); StreamTableEnvironment tableEnv = StreamTableEnvironment.create(env); // 构造测试DataStream DataStream<Order> dataStream = env.fromCollection(Arrays.asList( new Order(2L, "pen", 1, Arrays.asList("name01", "name02", "name03"), Arrays.asList(1, 2, 3)) )); // 转换为Table并对齐字段名 Table inputTable = tableEnv.fromDataStream(dataStream, $("user").as("user_a"), $("product"), $("amount"), $("name_list"), $("id_list") ); // 注册临时视图 tableEnv.createTemporaryView("InputTable", inputTable); // 创建sink表,修正amount类型为INT,补充ClickHouse连接器配置 tableEnv.executeSql("CREATE TABLE sink_table (\n" + " `user_a` BIGINT,\n" + " `product` VARCHAR,\n" + " `amount` INT,\n" + " `name_list` ARRAY<STRING>,\n" + " `id_list` ARRAY<INT>,\n" + " PRIMARY KEY (user_a) NOT ENFORCED\n" + ") WITH (\n" + " 'connector' = 'clickhouse',\n" + " 'url' = 'jdbc:clickhouse://你的ClickHouse地址:端口/数据库名',\n" + " 'table-name' = '对应ClickHouse侧的表名',\n" + " 'username' = '账号',\n" + " 'password' = '密码'\n" + ")"); // 执行插入,无需再调用env.execute() tableEnv.executeSql("INSERT INTO sink_table SELECT user_a, product, amount, name_list, id_list FROM InputTable"); } // 修正后的POJO类,添加无参构造、全参构造、getter/setter public static class Order { private Long user; private String product; private Integer amount; private List<String> name_list; private List<Integer> id_list; // 无参构造,Flink POJO要求必须有 public Order() {} // 全参构造,用于构造测试数据 public Order(Long user, String product, Integer amount, List<String> name_list, List<Integer> id_list) { this.user = user; this.product = product; this.amount = amount; this.name_list = name_list; this.id_list = id_list; } // 以下为所有属性的getter和setter public Long getUser() { return user; } public void setUser(Long user) { this.user = user; } public String getProduct() { return product; } public void setProduct(String product) { this.product = product; } public Integer getAmount() { return amount; } public void setAmount(Integer amount) { this.amount = amount; } public List<String> getName_list() { return name_list; } public void setName_list(List<String> name_list) { this.name_list = name_list; } public List<Integer> getId_list() { return id_list; } public void setId_list(List<Integer> id_list) { this.id_list = id_list; } } }
关键说明
- Flink原生支持Java
java.util.List类型到SQLARRAY类型的自动映射,只要List的元素类型和ARRAY定义的元素类型一致即可正常使用,无需额外配置。 - 对接ClickHouse时,需要保证ClickHouse侧表的对应字段类型也为Array类型,例如
Array(String)对应Flink的ARRAY<STRING>、Array(Int32)对应Flink的ARRAY<INT>。
内容的提问来源于stack exchange,提问作者xiaomaiyun
相关产品推荐
相关产品推荐

