Использование LocalDateTime в качестве поля @Version с Hibernate 5.3 / JPA 2.2 на Java 11 приводит к StaleObjectStateException

Рассмотрим объект под названием Template с полем:

@Version
@Column(name = "LAST_UPDATE", nullable = false)
private LocalDateTime lastUpdate; // Java 8's class

Поле резервной базы данных Oracle TIMESTAMP.

Теперь выполняем следующий код:

        // 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();

Вызывает исключение:

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

Если я изменю тип lastUpdate к java.sql.Timestamp, код работает правильно. В чем может быть проблема?

Хотя в документации это точно не указано, я думаю, что Hibernate поддерживает этот тип как поле @Version.

Тестовый пример доступен здесь: https://github.com/imeszaros/jooby-hbm-localdatetime

0 ответов

Для справки: Oracle TIMESTAMP По умолчанию тип имеет точность 6, которая может хранить только миллисекунды.

Java LocalDateTime однако может иметь наносекунды, поэтому вам нужно использовать TIMESTAMP(9) в базе данных, чтобы иметь возможность хранить значения без потери точности.

Другие вопросы по тегам