如何将 Jooq 用于尚不存在的 table?

How to use Jooq for a table that doesn't exist yet?

我有一个带有 Table Cdr 的数据库 (postgresql)。每个月都会在数据库中创建一个新的 table,它与 Table Cdr 具有相同的架构,名为 Cdr__(例如 Cdr_2016_04)。

我正在尝试使用 Jooq 根据提供的日期查询数据库。麻烦的是:

context.select(CDR.fields())
            .from("cdr_2017_01")
            .where(CDR.FIELD1.eq("somevalue")
                .and(CDR.FIELD2.notEqual("value 2")
                .and(CDR.FIELD2.notEqual("value 3")))
            .fetchInto(Cdr.class);

不起作用,因为它表明

org.jooq.exception.DataAccessException: ...from cdr_2017_01 where ("public"."cdr"."field1" = ? and "public"."cdr"."field2" <> ? and "public"."cdr"."field2" <> ?)]; ERROR: missing FROM-clause entry for table "cdr"

我试过使用别名来创建它 'cdr_2017_01 as cdr',但是失败了,因为 cdr 已经存在。好像是因为我用了CDR.FIELD1,还有CDR.fields(),jooq要求from子句中的table是CDR。有什么方法可以使它通用,还是我不应该使用 Jooq 进行这种查询?

错误

您遇到的错误源于您在字段引用中使用了生成的 CDR 文字,例如CDR.FIELD1。所有这些字段都将使用 "cdr" table 完全限定,而不是您在 from 子句中输入的 "cdr_2017_01" table。

您可以打开 debug logging 以查看 jOOQ 生成并发送到服务器的格式化 SQL 字符串。

解决方法

最简单的解决方法是将您的 "cdr_2017_01" table 别名改回 "cdr",如下所示:

context.select(CDR.fields())
        .from("cdr_2017_01 as cdr")
        .where(CDR.FIELD1.eq("somevalue")
            .and(CDR.FIELD2.notEqual("value 2")
            .and(CDR.FIELD2.notEqual("value 3")))
        .fetchInto(Cdr.class);

这在一定程度上适用于大多数查询。

更好的解决方案

您应该为此使用 runtime schema / table mapping feature。它正是为这些 multi-tenancy / 分区 use-cases.

设计的

然后您可以按照以下方式写一些东西:

DSL.using(connection, new Settings()
       .withRenderMapping(new RenderMapping()
           .withSchemata(new MappedSchema()
               .withInput("my_schema_name")
               .withTables(new MappedTable()
                   .withInput(CDR.getName())
                   .withOutput(CDR.getName() + "_2017_01")))))
   .select(CDR.fields())
   .from(CDR)
   .where(CDR.FIELD1.eq("somevalue")
       .and(CDR.FIELD2.notEqual("value 2")
       .and(CDR.FIELD2.notEqual("value 3")))
   .fetchInto(Cdr.class);

当然,另一种选择可能是使用 PostgreSQL 的分区功能,在这种情况下,您可能不需要在客户端中明确指定 table 名称:

https://www.postgresql.org/docs/current/static/ddl-partitioning.html