简体   繁体   English

使用 Spring Data JDBC 不支持的类型的查询参数?

[英]Using query parameter of type not supported in Spring Data JDBC?

I tried to write a query method in my repository similar to this我试图在我的存储库中编写一个类似于此的查询方法

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

When executing the code I got the following error:执行代码时,我收到以下错误:

org.postgresql.util.PSQLException: Can't infer the SQL type to use for an instance of java.time.Instant. org.postgresql.util.PSQLException:无法推断用于 java.time.Instant 实例的 SQL 类型。 Use setObject() with an explicit Types value to specify the type to use.使用带有显式 Types 值的 setObject() 来指定要使用的类型。

Did I forget something or is usage of Instant as parameter simply not supported by Spring Data Jdbc?我是否忘记了某些东西,或者 Spring Data Jdbc 根本不支持使用 Instant 作为参数? If so, is such a support planned in the future?如果是这样,未来是否计划提供此类支持?

Spring Data JDBC has no knowledge of the type expected by the SQL-statement. Spring Data JDBC 不知道 SQL 语句所期望的类型。 Therefore it passes parameters a long without any conversion and relies on the database to properly handle the parameter.因此,它在没有任何转换的情况下传递参数很长一段时间,并依赖于数据库来正确处理参数。

One might argue that it should convert parameters if a matching converter is registered, but this is currently not the case.有人可能会争辩说,如果注册了匹配的转换器,它应该转换参数,但目前情况并非如此。

Therefore currently the solution is to convert the argument yourself and changing the argument type to java.util.Date or whatever your JDBC driver is accepting.因此,目前的解决方案是自己转换参数并将参数类型更改为java.util.Date或您的 JDBC 驱动程序接受的任何内容。

For those who came here looking for a solution to generate java.sql.Timestamp instances with better than millisecond precision (the Timestamp constructor that accepts nanos is deprecated):对于那些来到这里寻找解决方案来生成具有优于毫秒精度的java.sql.Timestamp实例的人(不推荐使用接受 nanos 的Timestamp构造函数):

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

This assumes your operating system supports better than millisecond precision for the system clock.这假设您的操作系统支持系统时钟优于毫秒的精度。 It's useful for databases that support better-than-millisecond TIMESTAMP precision, such as with PostgreSQL, which supports microsecond precision.它对于支持优于毫秒 TIMESTAMP 精度的数据库很有用,例如支持微秒精度的 PostgreSQL。

You can convert it back to an Instant or LocalDateTime :您可以将其转换回InstantLocalDateTime

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

or或者

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

I will also reiterate information stoetti provided in a comment, that according to the documentation link that stoetti provided,https://jdbc.postgresql.org/documentation/head/8-date-time.html , the PostgreSQL JDBC driver does recognize the following java.time classes as timestamps:我还将重申 stoetti 在评论中提供的信息,根据 stoetti 提供的文档链接https://jdbc.postgresql.org/documentation/head/8-date-time.html,PostgreSQL JDBC 驱动程序确实识别以下java.time类作为时间戳:

java.time.LocalTime as TIME [ WITHOUT TIMEZONE ] java.time.LocalTime作为TIME [ WITHOUT TIMEZONE ]

java.time.LocalDateTime as TIMESTAMP [ WITHOUT TIMEZONE ] java.time.LocalDateTime作为TIMESTAMP [ WITHOUT TIMEZONE ]

java.time.OffsetDateTime as TIMESTAMP WITH TIMEZONE java.time.OffsetDateTime作为TIMESTAMP WITH TIMEZONE

But not java.time.Instant , as stoetti pointed out.但不是java.time.Instant ,正如 stoetti 指出的那样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM