无法在 Kotlin/Java 中使用 jooq DSL 执行 where 子句

Posted

技术标签:

【中文标题】无法在 Kotlin/Java 中使用 jooq DSL 执行 where 子句【英文标题】:cannot do a where clause with jooq DSL in Kotlin/Java 【发布时间】:2021-12-19 18:52:53 【问题描述】:

我正在尝试在 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"

【问题讨论】:

只是一个疯狂的猜测,但可能是数据类型问题? jooq.org/doc/latest/manual/sql-building/column-expressions/…除此之外,还有什么特别的原因,你为什么要使用 DSL.field("xyz")?使用 Kotlin 时,可以按原样导入数据类,使用 jooq 大写语法访问字段。 @nulldroid 所以,我尝试将这些转换为DSL.timestamp 并得到错误"Not supported by dialect : Type class org.jooq.impl.Val is not supported in dialect POSTGRES" 抱歉含糊不清,我也真的不在置信空间中。你的数据类叫什么?假设它被称为“交易”,我相信您会导入它并执行以下操作:Transaction.TIMESTAMP.between...blog.jooq.org/… @dulldroid 我感谢任何讨论!这对我来说是个问题。我想即时构建它,因此where 过滤器列由用户动态选择。我会暂时尝试一些硬编码值,看看我是否可以让它工作...... 你使用什么版本的jooq?无法重现 - 此代码 works fine 在我的机器上使用 org.jooq:jooq:3.15.4 【参考方案1】:

不使用代码生成器:

我假设您有充分的理由不使用 code generator 进行此特定查询,主要原因通常是您的架构是动态的。

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

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,只需将OffsetDateTime 替换为LocalDateTime...

使用代码生成器

如果使用代码生成器,如果您的架构不是动态的,总是推荐使用该代码生成器,您可以编写与上面几乎相同的内容,但键入安全:

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())

【讨论】:

感谢您的回复!我之前尝试过这个以及 LocalDateTime ...不知何故我在调试器中的 SQL 查询总是显示为:``` "sql_query":"select * from data_table where ts between cast(? as timestamp with timezone) and cast(?作为带有时区的时间戳)按 id desc 顺序仅获取下 1000 行 ``` 我不明白为什么 ? 以及为什么实际值没有被呈现... 为什么不呢?绑定变量很好。但这不是您在这里遇到的主要问题。如果您提出一个新问题,我也很乐意回答这个问题,具体包括为什么困扰您。 啊好吧,那是因为绑定。抱歉,我对此非常陌生,所以仍在寻找我的脚。我会尽快更新问题。 我希望能给你买杯啤酒。最后的评论就是一切。我需要一个DSL.inline

以上是关于无法在 Kotlin/Java 中使用 jooq DSL 执行 where 子句的主要内容,如果未能解决你的问题,请参考以下文章

jooq无法在游戏中生成类 - scala

jOOQ 无法映射 PostgreSQL 列以使 JPA 满意

jooq + scala 代码生成:对象 AbstractKeys 中的方法 createIndex 无法在对象 org.jooq.impl.AbstractKeys 中访问

SQLite 无法通过 JDBC 和 jOOQ 在 SELECT 中找到现有列

无法使用 gradle-jooq-plugin-3.0.1、jooq-3.11.2 找到或加载主类 org.jooq.codegen.GenerationTool

无法在 Kotlin 中使用 jooq UpdateQuery 在数据库中将非字符串值设置为 null