[Spring bot3 + h2 v.2.1.214] H2 failing to fetch Java Instant.

520 views
Skip to first unread message

ChereGG

unread,
Apr 21, 2023, 10:41:13 AM4/21/23
to H2 Database
As I mentioned here:
I have a problem with hy h2 DataJpaTest after migrating the app to Spring boot 3. It fails to fetch the Instant fields in my projection, the error being: "java.lang.UnsupportedOperationException: Cannot project java.time.OffsetDateTime to java.time.Instant; Target type is not an interface and no matching Converter found"
Any ideas? 
Thank you!

Evgenij Ryazanov

unread,
Apr 21, 2023, 11:51:57 AM4/21/23
to H2 Database
Hello!

This problem is not related to H2 at all.

H2 by itself can return TIMESTAMP WITH TIME ZONE and compatible values as java.time.Instant from its JDBC driver if it is explicitly requested.

try (Connection c = DriverManager.getConnection("jdbc:h2:mem:")) {

ResultSet rs = c.createStatement().executeQuery("VALUES TIMESTAMP WITH TIME ZONE '2023-01-02 03:04:05.123456789+00'");

rs.next();

System.out.println(rs.getObject(1, Instant.class));

}


But when you use some library on top of JDBC, you need to ensure that this library also supports java.time.Instant values. This Java type is not a part of JDBC specification and only few drivers (including driver of H2) support it natively. Java persistence libraries also aren't required to know this data type. It looks like you need to write an own data type converter. For example, in JPA, converters implement jakarta.persistence.AttributeConverter or javax.persistence.AttributeConverter depending on version of JPA implementation. In your case an implementation of org.springframework.core.convert.converter.Converter seems to be required. spring-data-commons project has org.springframework.data.convert.Jsr310Converters class with some converters for java.time.Instant type, but it doesn't have a converter between java.time.OffsetDateTime (JDBC data type for TIMESTAMP WITH TIME ZONE SQL data type) and java.time.Instant.

ChereGG

unread,
Apr 24, 2023, 3:17:22 AM4/24/23
to H2 Database
I see what you are saying, the thing is, outside of the tests, the queries are working perfectly as they are, and before the version updates it worked fine in tests as well. The fact that the problem only shows up when using h2 made me think that it is a h2 related problem.

Evgenij Ryazanov

unread,
Apr 24, 2023, 3:36:14 AM4/24/23
to H2 Database
MySQL mentioned in your question on StackOverflow doesn't have the TIMESTAMP WITH TIME ZONE data type. It means your application uses different data types with different database systems.

JDBC drivers by default return TIMESTAMP values as java.sql.Timestamp (R2DBC returns them as java.time.LocalDateTime).

Both JDBC and R2DBC drivers return TIMESTAMP WITH TIME ZONE values as java.time.OffsetDateTime.

spring-data-commons is able to convert LocalDateTime to Instant, but it doesn't have a built-in converter from OffsetDateTime to Instant.

ChereGG

unread,
Apr 24, 2023, 9:06:50 AM4/24/23
to H2 Database
You are right! Creating a custom converter solved the issue. I'm not sure tho why did this issue pop-up only now.
Thank you so much for the help! Have a great day!

Reply all
Reply to author
Forward
0 new messages