Использование параметра запроса типа, не поддерживаемого в Spring Data JDBC?

Я попытался написать метод запроса в своем репозитории, подобный этому

@Modifying
@Query("UPDATE foo SET some_timestamp = :someTimestamp WHERE id = :id")
void updateSomeTimestamp(@Param("id") long id, @Param("someTimestamp") Instant someTimestamp)

При выполнении кода я получил следующую ошибку:

org.postgresql.util.PSQLException: невозможно определить тип SQL для использования в экземпляре java.time.Instant. Используйте setObject() с явным значением Types, чтобы указать используемый тип.

Я что-то забыл или использование Instant в качестве параметра просто не поддерживается Spring Data Jdbc? Если да, то планируется ли такая поддержка в будущем?


person stoetti    schedule 19.12.2019    source источник


Ответы (2)


Spring Data JDBC ничего не знает о типе, ожидаемом оператором SQL. Поэтому он передает параметры без какого-либо преобразования и полагается на базу данных для правильной обработки параметра.

Можно возразить, что он должен преобразовывать параметры, если зарегистрирован соответствующий преобразователь, но в настоящее время это не так.

Поэтому в настоящее время решение состоит в том, чтобы преобразовать аргумент самостоятельно и изменить тип аргумента на java.util.Date или любой другой, который принимает ваш драйвер JDBC.

person Jens Schauder    schedule 19.12.2019
comment
Я понимаю вашу точку зрения, но, по моему мнению, java.time.* — это набор классов, которые должны поддерживаться из коробки. - person stoetti; 19.12.2019
comment
Я как бы согласен и сделал бы это дело против драйвера JDBC. Возникает вопрос: следует ли Spring Data JDBC пытаться преобразовать параметры? - person Jens Schauder; 19.12.2019
comment
Согласно документации (по крайней мере, для postgresql-диска, который мы используем) поддерживаются некоторые классы из java.time, Instant не включен. =› jdbc.postgresql.org/documentation/head/8-date- time.html На мой взгляд, преобразование параметров из java.time.* в некоторый jdbc-совместимый тип было бы хорошей функцией, от которой, я думаю, выиграет больше пользователей Spring Data JDBC. - person stoetti; 19.12.2019
comment
Для этого я создал jira.spring.io/browse/DATAJDBC-464. - person Jens Schauder; 20.12.2019

Для тех, кто пришел сюда в поисках решения для создания экземпляров java.sql.Timestamp с точностью выше миллисекунды (конструктор Timestamp, который принимает nano, устарел):

Timestamp timestamp = Timestamp.from(Instant.now());

Это предполагает, что ваша операционная система поддерживает точность системных часов выше миллисекунды. Это полезно для баз данных, которые поддерживают точность TIMESTAMP выше миллисекунды, например, в PostgreSQL, который поддерживает точность до микросекунд.

Вы можете преобразовать его обратно в Instant или LocalDateTime:

System.out.println(timestamp.toInstant()); // UTC

or

System.out.println(timestamp.toLocalDateTime()); // local time

Я также повторю информацию, предоставленную stoetti в комментарии, что, согласно ссылке на документацию, предоставленной stoetti, https://jdbc.postgresql.org/documentation/head/8-date-time.html, драйвер JDBC PostgreSQL распознает следующие java.time классы как метки времени:

java.time.LocalTime as TIME [ WITHOUT TIMEZONE ]

java.time.LocalDateTime as TIMESTAMP [ WITHOUT TIMEZONE ]

java.time.OffsetDateTime as TIMESTAMP WITH TIMEZONE

Но не java.time.Instant, как указал Стоэтти.

person acker9    schedule 16.01.2020