Jpa - Hibernate @Version неправильно увеличен - PullRequest
11 голосов
/ 30 сентября 2011

Я использую jpa с hibernate (3.2.7) в качестве реализации orm. Я изменил сущность, а затем слил ее. У меня также есть @EntityListeners для этой сущности, чтобы гарантировать, что некоторый атрибут оценивается.

Если я изменю значение до слияния, а затем верну это значение в методе @PreUpdate в Listener, установив исходное значение, моя версия для результатов сущности увеличится, но для версии базы данных будет иметь предыдущее значение. Я думаю, что это связано с тем, что объект не изменился, поэтому на БД он не обновляется, но версия объекта была увеличена без восстановления после сброса.

Чтобы объяснить лучше, у меня есть этот объект:

@Entity
@EntityListeners({MyListener.class})
public class MyEntity {

    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO)   
    private Long id;

    private String myValue;

    @Version    
    private Long version ;
}

и этот слушатель:

public class MyListener {

    @PreUpdate
    public void preUpdate(MyEntity ua) { 
        ua.setMyValue("default");
    }
}

Теперь предположим, что у меня есть на БД объект со следующими значениями: (id = 1, myValue = 'defalut', version = 1). Я читаю этот объект, отсоединяюсь, передаю его клиенту и возвращаю его с помощью myValue = 'new' и выполняю операцию слияния (слушатель меняет myValue на 'default' и, таким образом, результат объекта остается неизменным в db), сбрасывается и выходит из транзакции (так стремится). После этого я нахожу версию = 2 для моего объекта, но версию = 1 для базы данных.

Это ошибка в спящем режиме? Или ошибка Jpa?

Ответы [ 2 ]

2 голосов
/ 26 апреля 2012

Я бы сказал, что это ожидаемое поведение. Согласно инструкции Hibernate , @PreUpdate означает «Выполнено перед операцией ОБНОВЛЕНИЕ базы данных». Итак, Hibernate уже понял, что он должен выполнить UPDATE, запустив грязную проверку и вернув true.

Грязная проверка не может произойти ПОСЛЕ @PreUpdate, потому что Hibernate не должен вызывать @PreUpdate, если грязная проверка не является истинной. И если обновление будет запущено, версию следует увеличить.

Вы думали об использовании слушателя для @PrePersist вместо @PreUpdate? Я считаю, что это достаточно рано в процессе, что это будет предварительная проверка, и, следовательно, будет иметь поведение, которое вы хотите.

0 голосов
/ 24 июня 2012

Для меня это выглядит как нарушение спецификации. Или, может быть, это слишком сильная формулировка, лучше, вероятно, сказать, что такой угловой случай недостаточно четко указан. Спецификация JPA 1.0 (Hibernate 3.2.7 является одной из реализаций) довольно четко прописывает, когда нужно обновить версию:

Атрибут версии обновляется средой выполнения поставщика сохраняемости. когда объект записывается в базу данных.

Также громко задается базовый атрибут в вызываемой сущности (JPA 2.0):

Метод обратного вызова жизненного цикла может изменить состояние отсутствия связи сущность, на которую она вызывается.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...