代码之家  ›  专栏  ›  技术社区  ›  Evan

使用生成的代码和distinctOn进行Jooq-select查询

  •  0
  • Evan  · 技术社区  · 4 年前

    我一直在使用Jooq生成的代码模式进行以下查询:

    List<Model> results =
        dsl.selectFrom(TABLE_NAME)
           .where(TABLE_NAME.ID.eq(id))
           .fetchInto(Model.class);
    

    这与RecordMapperProvider一起根据表和模型类确定使用哪个RecordMapper:

    RecordMapperProvider recordMapperProvider = new RecordMapperProvider() {
                @Override
                public <R extends Record, E> RecordMapper<R, E> provide(final RecordType<R> recordType,
                                                                        final Class<? extends E> type) {
                    return (RecordMapper<R, E>) recordMappers.getOrDefault(new RecordMapperKey(recordType, type),
                                                                           new DefaultRecordMapper<>(recordType, type));
                }
            };
    

    这是我试图实现的一个例子:

    List<Model> results =
        dsl.select(TABLE_NAME.fields())
           .distinctOn(TABLE_NAME.DIFF_COL)
           .from(TABLE_NAME)
           .where(buildConditions(criteria))
           .orderBy(TABLE_NAME.PKEY_COL,
                    TABLE_NAME.TS_COL.desc())
           fetchInto(Model.class);
    

    新查询包含distinctOn组件,它正在更改传递给RecordMapperProvider的RecordType。此新的RecordType不再与生成的代码匹配。

    我的问题是:是否有一种解决方案,我可以在生成的代码中保留原始的RecordType,并在查询中使用distinctOn时仍然使用此RecordMapperProvider模式?

    我遍历了Jooq库,看看如何比较RecordType对象,发现它们的相等性是基于查询中返回的字段集。我在想,如果我可以使用一个新的比较器来确定一个RecordType是否是另一个RecordType的子集,那么它仍然可以工作。但是,我发现原始查询中的字段与生成的代码不匹配,无法使用distinctOn返回查询中的内容。

    0 回复  |  直到 4 年前
        1
  •  0
  •   Evan    4 年前

    在这里找到了答案: https://www.jooq.org/doc/latest/manual/sql-execution/fetching/record-vs-tablerecord/

    我能够将原始记录插入到为我正在查询的表生成的TableRecord中:

    List<MyDisplayRecord> records =
    dsl.select(TABLE_NAME.fields())
       .distinctOn(TABLE_NAME.DIFF_COL)
       .from(TABLE_NAME)
       .where(buildConditions(criteria))
       .orderBy(TABLE_NAME.PKEY_COL,
                TABLE_NAME.TS_COL.desc())
       fetchInto(MyTable.TABLE.getRecordType());
    MyRecordMapper mapper = new MyRecordMapper();
    
    return records.stream().map(mapper::map).collect(toList());
    

    通过这种方式,我能够使用这种查询结构重用映射器。