Explain why datetime types for @Version get OLE using >= Java 15

Hibernate before version 6 generates a value with Instant.now() so it uses nanosecond precision on JDK15+ and stores that in memory as version for an entity.

On insert, it passes a Timestamp with these nanos to the JDBC driver to an insert into .... In this case, the database will do this truncation/rounding based on the column it inserts into.

Now when updating that entity, it will do something like this: update tbl set col1 = ?, version = ? where id = ? and version = ?. The set clause param will be bound to the new version and the where clause param to the old version. Again, a Timestamp with nanos is passed to the JDBC driver.

Now, MySQL is like other production ready databases sane and coerces params based on the context to the appropriate data type and does the same truncation/rounding to precision 6 to both parameters.
H2 on the other hand, does not seem to do so for the comparison in the where clause, and hence the predicate is false and update doesn’t do anything, finally failing with an OLE.

This is a H2 issue and they have similar issues with collations when comparing char(N) even with string literals. The only solution for you if you must use H2 is to register a custom version of the InstantJavaType in Hibernate that produces a value with precision 6.

1 Like