Consider an entity called Template
with a field:
@Version
@Column(name = "LAST_UPDATE", nullable = false)
private LocalDateTime lastUpdate; // Java 8's class
The backing Oracle database field is TIMESTAMP
.
Now executing the following code:
// get EntityManager, start transaction
final var t = new Template();
t.setName("new template");
t.setSubject("subject");
em.persist(t);
t.setSubject("subject - mod");
tx.commit();
Causes an exception to be thrown:
Caused by: org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [Template#169]
at org.hibernate.persister.entity.AbstractEntityPersister.check(AbstractEntityPersister.java:2525)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3357)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3231)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3632)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:146)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:478)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:356)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1453)
... 59 common frames omitted
If I change the type of lastUpdate
to java.sql.Timestamp
, the code works properly. What could be the problem?
Although not stated exactly in the docs, i think Hibernate supports this type as @Version field.
A test case is available here: https://github.com/imeszaros/jooby-hbm-localdatetime
Just for the record: Oracle's TIMESTAMP
type has a precision of 6 by default, which can only store milliseconds.
Java's LocalDateTime
however may have nanoseconds, therefore you need to use TIMESTAMP(9)
in the database to be able to store the values without the loss of precision.