1

我们正在尝试执行 dml,它根据 ZonedDateTime 删除记录。我们正在使用以下代码,但遇到了错误。

dsl.execute ("delete from fieldhistory where createddate <= ? and object = ?", beforeDate.toOffsetDateTime(), objName)

beforeDateZonedDateTime在哪里,objectName是字符串

我们从 postgres 收到以下错误。

org.jooq.exception.DataAccessException: SQL [delete from fieldhistory where createddate <= ? and object = ?]; ERROR: operator does not exist: timestamp with time zone <= character varying
  Hint: No operator matches the given name and argument types. You might need to add explicit type casts.
  Position: 56
    at org.jooq_3.13.1.POSTGRES.debug(Unknown Source)
    at org.jooq.impl.Tools.translate(Tools.java:2751)
    at org.jooq.impl.DefaultExecuteContext.sqlException(DefaultExecuteContext.java:755)
    at org.jooq.impl.AbstractQuery.execute(AbstractQuery.java:385)
    at org.jooq.impl.DefaultDSLContext.execute(DefaultDSLContext.java:1144)

问题是,我们如何在 Jooq 中绑定日期时间值?

4

1 回答 1

2

由于历史原因,jOOQ 将所有 JSR-310 时间绑定为字符串,而不是相关的对象类型。这是因为直到最近,JDBC 驱动程序本身并不支持 JSR-310 类型,因此,使用字符串并不是一个糟糕的默认值。

不幸的是,这会导致类型歧义,如果以下任何一种情况都不会出现这种情况:

  • jOOQ 没有绑定字符串
  • 您正在使用代码生成器,因此键入安全的 DSL API 方法

作为一种解决方法,您可以做一些事情,包括:

显式转换绑定变量

dsl.execute("delete from fieldhistory where createddate <= ?::timestamptz and object = ?",  
    beforeDate.toOffsetDateTime(), 
    objName)

使用 DSL API

dsl.deleteFrom(FIELDHISTORY)
   .where(FIELDHISTORY.CREATEDDATE.lt(beforeDate.toOffsetDateTime()))
   .and(FIELDHISTORY.OBJECT.eq(objName))
   .execute();

通过编写自己的绑定

您可以编写自己的数据类型绑定并将其附加到生成的代码或普通 SQL 查询中,在这种情况下,您可以控制绑定变量如何发送到 JDBC 驱动程序。请参阅: https ://www.jooq.org/doc/latest/manual/sql-building/queryparts/custom-bindings/

例如:

DataType<OffsetDateTime> myType = SQLDataType.OFFSETDATETIME
                                             .asConvertedDataType(new MyBinding());
dsl.execute ("delete from fieldhistory where createddate <= {0} and object = {1}", 
    val(beforeDate.toOffsetDateTime(), myType), 
    val(objName))

将来会对此进行修复,因此不再需要:https ://github.com/jOOQ/jOOQ/issues/9902

于 2020-02-28T15:26:48.890 回答