无法在 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 无法映射 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