首页 > 解决方案 > 无法在 Kotlin/Java 中使用 jooq DSL 执行 where 子句

问题描述

我正在尝试在 Kotlin 中使用 jooq 运行以下形式的查询:

val create = DSL.using(SQLDialect.POSTGRES)
val query: Query = create.select().from(DSL.table(tableName))
            .where(DSL.field("timestamp").between("1970-01-01T00:00:00Z").and("2021-11-05T00:00:00Z"))
            .orderBy(DSL.field("id").desc())

上面的代码给了我:

syntax error at or near \"and\

此外,在调试器中查看此查询,query.sql呈现为:

select * from data_table where timestamp between ? and ? order by id desc 

我不确定这是否?表明它无法将值呈现给 SQL,或者它们是某种占位符..

此外,代码可以在没有where链的情况下工作。

此外,在 Postgres 命令行上,我可以运行以下命令并执行查询:

select * from data_table where timestamp between '1970-01-01T00:00:00Z' and '2021-11-05T00:00:00Z' order by id

查询架构上的数据类型,timestamp列类型呈现为timestamp without time zone.

在我将变量声明为:

val lowFilter = "1970-01-01T00:00:00Z"
val highFilter = "2021-11-05T00:00:00Z"

这不起作用,似乎传递原始字符串也不起作用。我对此很陌生,所以我很确定我在这里搞乱了用法。

编辑 遵循@nulldroid 的建议,做了类似的事情:

.where(DSL.field("starttime").between(DSL.timestamp("1970-01-01T00:00:00Z")).and(DSL.timestamp("2021-11-05T00:00:00Z")))

这导致:

Type class org.jooq.impl.Val is not supported in dialect POSTGRES"

标签: kotlinjooq

解决方案


不使用代码生成器:

我将假设您有充分的理由不为这个特定的查询使用代码生成器,主要原因通常是您的模式是动态的。

因此,编写查询的正确方法是:

create.select()
      .from(DSL.table(tableName))

      // Attach a DataType to your timestamp field, to let jOOQ know about this
      .where(DSL.field("timestamp", SQLDataType.OFFSETDATETIME)

          // Use bind values of a temporal type
          .between(OffsetDateTime.parse("1970-01-01T00:00:00Z"))
          .and(OffsetDateTime.parse("2021-11-05T00:00:00Z")))
      .orderBy(DSL.field("id").desc())

请注意我如何使用实际的时间数据类型,而不是字符串来比较日期和声明字段。

我假设,根据您的问题的 UTC 时间戳,您正在使用TIMESTAMPTZ. 否则,如果您正在使用TIMESTAMP,只需替换OffsetDateTimeLocalDateTime...

使用代码生成器

如果使用代码生成器(如果您的架构不是动态的,则始终建议使用该代码生成器),您将编写与上面几乎相同的内容,但键入安全:

create.select()
      .from(MY_TABLE)

      // Attach a DataType to your timestamp field, to let jOOQ know about this
      .where(MY_TABLE.TIMESTAMP

          // Use bind values of a temporal type
          .between(OffsetDateTime.parse("1970-01-01T00:00:00Z"))
          .and(OffsetDateTime.parse("2021-11-05T00:00:00Z")))
      .orderBy(MY_TABLE.ID.desc())

推荐阅读