Привязка ошибок OffsetDateTime [оператор не существует: временная метка с часовым поясом <= изменение символа] - PullRequest
0 голосов
/ 24 февраля 2020

Мы пытаемся выполнить dml, который удаляет записи на основе ZonedDateTime. Мы используем следующий код, но сталкиваемся с ошибкой.

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

Где beforeDate - ZonedDateTime, а 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?

1 Ответ

1 голос
/ 28 февраля 2020

По историческим причинам c jOOQ связывает все JSR-310 раз как строки, а не как соответствующий тип объекта. Это связано с тем, что до недавнего времени драйверы JDB C изначально не поддерживали типы 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 в В этом случае вы будете контролировать, как переменная связывания отправляется в драйвер JDB C. См .: 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

...