JOOQ:多转换器联合查询中第二个临时转换器被忽略
解决JOOQ联合查询中第二个转换器失效的问题
你遇到的问题是:在JOOQ的unionAll联合查询里,第二个查询指定的mapping(B::new)没有生效,所有结果都被转换成了第一个查询的A类型。这是JOOQ联合查询的特性导致的——它会以第一个SELECT语句的结果类型作为整个联合查询的统一输出类型,后续查询的映射规则会被自动覆盖。
解决方案1:分别查询后合并结果
最直接的方法是分开执行两个查询,再把结果合并。这样每个查询的映射规则都会独立生效:
// 查询表A,映射为A类型 List<Something> listA = db.select(row(TABLE_A.ID, TABLE_A.NAME).mapping(A::new)) .from(TABLE_A) .fetch(Record1::component1); // 查询表B,映射为B类型 List<Something> listB = db.select(row(TABLE_B.ID, TABLE_B.NAME).mapping(B::new)) .from(TABLE_B) .fetch(Record1::component1); // 合并结果 List<Something> allRecords = new ArrayList<>(); allRecords.addAll(listA); allRecords.addAll(listB);
解决方案2:添加类型标识,在fetch阶段手动映射
如果必须用联合查询,可以给每个子查询添加一个类型标识字段,在最终fetch的时候根据标识来创建对应类型的对象:
List<Something> allRecords = db.select( // 给表A的结果加类型标识"A" row(TABLE_A.ID, TABLE_A.NAME, val("A").as("record_type")) ) .from(TABLE_A) .unionAll( select( // 给表B的结果加类型标识"B" row(TABLE_B.ID, TABLE_B.NAME, val("B").as("record_type")) ).from(TABLE_B) ) .fetch(record -> { UInteger id = record.get(0, UInteger.class); String name = record.get(1, String.class); String type = record.get(2, String.class); return "A".equals(type) ? new A(id, name) : new B(id, name); });
注意事项
- 示例代码里的变量名
record建议改为records,因为接收的是集合,避免命名混淆。 - 第二种方案里,也可以用JOOQ的字段引用代替索引,比如
record.get(TABLE_A.ID),只要两个表的字段类型一致即可。
内容的提问来源于stack exchange,提问作者Matt Snider
相关产品推荐
相关产品推荐

