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
TIMESTAMPtype has a precision of 6 by default, which can only store milliseconds.Java's
LocalDateTimehowever may have nanoseconds, therefore you need to useTIMESTAMP(9)in the database to be able to store the values without the loss of precision.