java.time types not usable for optimistic locking due to precision truncation
Description
is duplicated by
Activity
Show:
Christian Beikov September 29, 2023 at 10:25 AM
Yeah, that looks like a good workaround for ORM 5.
Stefan Fußenegger September 22, 2023 at 3:51 PM
for anyone stuck with an earlier version I believe using a custom type extending InstantType
is the best workaround:
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.InstantType;
/**
* workaround for <a href="https://hibernate.atlassian.net/browse/HHH-15135">HHH-15135 java.time types not usable for
* optimistic locking due to precision truncation</a>
*/
public abstract class InstantPrecisionType extends InstantType {
private final ChronoUnit _unit;
private InstantPrecisionType(final ChronoUnit unit) {
_unit = unit;
}
@Override
public Instant seed(final SharedSessionContractImplementor session) {
return truncated(super.seed(session));
}
@Override
public Instant next(final Instant current, final SharedSessionContractImplementor session) {
return truncated(super.next(current, session));
}
private Instant truncated(final Instant instant) {
return instant == null ? null : instant.truncatedTo(_unit);
}
public class Millis extends InstantPrecisionType {
public Millis() {
super(ChronoUnit.MILLIS);
}
}
public class Micros extends InstantPrecisionType {
public Micros() {
super(ChronoUnit.MICROS);
}
}
public class Nanos extends InstantPrecisionType {
public Nanos() {
super(ChronoUnit.NANOS);
}
}
}
Usage with @Type
(and optionally @TypeDef
):
@Data
@Entity
@TypeDef(typeClass = InstantMillisType.class, name = "millis")
public class Foo {
@Version
@Type(type = "millis")
private Instant updated;
}
Maybe someone would like to confirm that this is a viable workaround? (Note @Convert
won’t work as it’s not suitable for @Version
properties)
Fixed
Assignee
Reporter
Christian Beikov
Christian BeikovComponents
Fix versions
Priority
Created March 21, 2022 at 5:19 PM
Updated September 29, 2023 at 10:25 AM
Resolved April 5, 2022 at 6:29 AM
It was reported (Java 17 @version and nanoseconds truncation ) that java.time types use nanosecond precision when generating version values. When the database only supports e.g. microseconds,
OptimisticLockException
can occur due to the truncation in SQL. Ideally, we would now pass in the requested precision information into theorg.hibernate.type.descriptor.java.VersionJavaType
methods to solve this, though that would be a breaking change between 6.0.0.CR and Final.