在 Jooq 中,如何获取到 LinkedHashMap?

In Jooq, how to fetch into LinkedHashMap?

我知道要获取到 Map 我可以使用 fetchMap,但它不支持 LinkedHashMap,我想在其中维护 [=16] 创建的插入顺序=].

我试过了

.
.
.
.orderBy(...)
.collect(
    Collectors.toMap(
        record -> record.field1(), 
        record -> record.field2(), 
        LinkedHashMap.class));

但是 field1field2 部分给了我以下错误。

Cannot resolve method 'field1' in 'T'

希望有人能帮帮我~

谢谢!

解法:

根据@Lukas的回答,试了几次,发现必须做到以下几点:

  1. select方法中,所有字段都必须有一个类型,除了那些计算的,添加类型会抛出field not found in field list错误。

  2. 要向字段添加类型,您必须使用 DSL.field(fieldname, type) 方法而不是 DSL.field(fieldname).cast(type)。后者会抛出 field not found in field list 错误。

  3. collect方法的collector对象中,获取记录的每个字段时,它们也必须有一个类型。喜欢

record -> record.get(DSL.field("fieldname", Float.class)),

完整的查询类似于:

Table<Record2<Long, Integer>> table1 = ...;
Table<Record2<Long, Integer>> table2 = ...;
.
.
.
return DSL.
        .select(table1.field("table1_field1", Long.class),
                DSL.ifnull(
                        table1.field("table1_field2", Float.class)
                                .div(table2.field("table2_field1", Float.class)),
                        0)
                        .as("result_table_field1"))
        .from(table1)
        .join(table2)
            .on(table1.field("table1_field1", Long.class)
                    .eq(table2.field("table2_field2", Long.class)))
        .orderBy(DSL.field("result_table_field1"))
        .collect(Collectors.toMap(
                record -> record.get(table1.field("table1_field1", Long.class)),
                record -> record.get(DSL.field("result_table_field1", Float.class)),
                (v1, v2) -> { throw new InvalidResultException("Duplicate key: " + v1); },
                LinkedHashMap::new
        ));

这两种方法都假设您使用的是 jOOQ code generator

fetchMap() 已经 returns 一个 LinkedHashMap

查看 fetchMap() Javadoc。它说:

The resulting map is iteration order preserving.

它实际上是一个 LinkedHashMap,虽然它不能保证这个确切的类型,所以你必须自担风险。

使用collect()

如果您编写的查询生成 Record2 类型,那么您可以像这样使用类型安全的收集器:

LinkedHashMap<T1, T2> map =
ctx.select(T.COL1, T.COL2)
   .from(T)
   .orderBy(...)
   .collect(Collectors.toMap(
       Record2::value1,
       Record2::value2,
       (v1, v2) -> { throw new InvalidResultException("Duplicate key: " + v1); },
       LinkedHashMap::new
   ));

您的尝试未通过编译的原因是:

  1. 您缺少 toMap()
  2. 的强制性 mergeFunction 参数
  3. 您应该使用 value1()value2(),而不是 field1()field2(),但这只有在您拥有类型安全的情况下才有效 Record2在你的结果集中
  4. 如果您没有 Record2,而是 Record,那么您可以在没有类型安全的情况下工作:
LinkedHashMap<T1, T2> map =
ctx.select(...)
   .from(T)
   .orderBy(...)
   .collect(Collectors.toMap(
       r -> r.get(T.COL1),
       r -> r.get(T.COL2),
       (v1, v2) -> { throw new InvalidResultException("Duplicate key: " + v1); },
       LinkedHashMap::new
   ));