我可以使用 jOOQ 将普通 SQL 查询映射到生成的 pojo 中吗?

Can I use jOOQ to map a plain SQL query into a generated pojo?

我正在 jOOQ 中执行一个简单的 sql 查询,并想将其映射到 jOOQ 生成的 pojo 中。我希望我能做到这样的事情:

public List<Foo> findFoos(final DateTime time) {
    return db.resultQuery(loadSqlQuery("FooRepository_findFoos"), time)
             .fetchInto(Foo.class);
}

但是这不起作用。这些字段没有映射到构建 Foo 所需的类型,因为字段定义是 DB 列的定义,而不是 FOO table 的映射类型。目前我的代码看起来像这样:

public List<Foo> findFoos(final DateTime time) {
    return db.resultQuery(loadSqlQuery("FooRepository_findFoos"), time)
             .fetch(r -> {
                 return new Foo(
                         new FooId(r.getValue(FOO.ID, UUID.class)),
                         new BarId(r.getValue(FOO.BAR_ID, UUID.class))
                         //etc
                 );
             });
}

有什么方法可以为结果查询提供我正在获取的 Field 列表,以便它可以正确映射结果?我希望某个地方有能力做这样的事情:

public List<Foo> findFoos(final DateTime time) {
    return db.resultQuery(loadSqlQuery("FooRepository_findFoos"), time)
             .fetch(FOO.fields())
             .into(Foo.class);
}

但是我找不到它。这是我忽略的地方还是不受支持?

作为参考,我使用普通 sql 的原因之一是让间隔在 PostgreSQL 中工作。例如(不是真正的查询)

select
    f.*
from foo f
where f.id not in (
    select
        x.foo_id
    from bar x
    where x.start_date >= (?::timestamptz - '1 year'::interval)
)

提前致谢。

jOOQ 3.12解决方案

jOOQ 3.12 实现 #4473,它允许将 ResultQuery<R1> 强制转换为新的众所周知的记录类型 ResultQuery<R2>(可能使用 ConverterBinding 配置)。

你可以这样写:

public List<Foo> findFoos(final DateTime time) {
    return db.resultQuery(loadSqlQuery("FooRepository_findFoos"), time)
             .coerce(FOO)
             .fetch();
}

jOOQ 3.11 及更早版本的解决方法

您不一定非得求助于普通 SQL。您可以这样做:

public List<Foo> findFoos(final DateTime time) {
    return db.select(FOO.fields())
             .from("({0}) AS {1}", 
                  DSL.sql(loadSqlQuery("FooRepository_findFoos"), time),
                  DSL.name(FOO.getName()))
             .fetchInto(Foo.class);
}

您必须确保 FOO.fields() 不会生成任何架构名称,例如通过指定 Settings.renderSchema = false