2011-09-30 12 views
11

Używam jpa z hibernacją (3.2.7) jako implementacja orm. Mam jednostkę, która jest modyfikowana, a następnie scalana. Mam również @EntityListeners na tym obiekcie, aby zapewnić wartość niektórych atrybutów.Jpa - Hibernuj @wersja niepoprawnie inkrementowana

Jeśli zmienię wartość przed scaleniem, a następnie zmienię tę wartość w metodzie @PreUpdate w odbiorniku, ustawiając oryginalną wartość, moja wersja wyników jednostki będzie inkrementowana, ale w wersji bazy danych ma poprzednią wartość. Myślę, że jest to spowodowane tym, że obiekt się nie zmienił, więc na db nie jest aktualizowany, ale wersja na jednostce została zwiększona bez przywracania po spłukaniu.

Aby lepiej wyjaśnić, mam ten obiekt:

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

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

    private String myValue; 

    @Version  
    private Long version ; 
} 

i ten Listener:

public class MyListener { 

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

Teraz Załóżmy, że mam na db obiektu z tych wartości: (id = 1, myValue = "defalut", wersja = 1). Czytam ten obiekt, odejmuję go, przekazuję go do klienta i odsyła z powrotem za pomocą myValue = "new" i wykonuję operację scalania (detektor zmienia wartość myValue na "default", a więc wynik obiektu jest niezmodyfikowany do db), opróżnia i kończy działanie (tak jest popełnione). Po tym, jak znajdę version = 2 na moim obiekcie, ale wersja = 1 na db.

Czy to jest błąd hibernacji? Lub bug Jpa?

+0

Czy można wspomnieć o hierarchii wywołania metody i sekwencji wywołania. Może twoja metoda scalania działa przed metodą aktualizacji. – mbaydar

+0

Domyślam się, że sprawdzanie w trybie hibernacji powoduje zwrócenie wartości false, więc obiekt nie dotyka DB (bez generowania zapytania o aktualizację), ale hibernacja prawdopodobnie zwiększa pole wersji przy pierwszym wywołaniu programu ustawiającego. IMHO pole wersji powinno być zwiększane tylko wtedy, gdy zaktualizowana wartość zostanie zapisana w bazie danych. To prawdopodobnie błąd hibernacji. –

Odpowiedz

2

Powiedziałbym, że to oczekiwane zachowanie. Zgodnie z Hibernate manual, @PreUpdate jest "Wykonane przed operacją aktualizacji bazy danych.". Tak więc Hibernate już zorientował się, że musi to zrobić UPDATE, uruchamiając brudny check i zwracając go true.

Brudne sprawdzenie nie może się zdarzyć PO @PreUpdate, ponieważ Hibernate nie powinien wywoływać @PreUpdate, chyba że sprawdzanie dirty jest prawdą. A jeśli aktualizacja ma zostać uruchomiona, wersja powinna zostać zwiększona.

Czy myślisz o użyciu detektora dla @PrePersist, zamiast @PreUpdate? Uważam, że jest wystarczająco wcześnie w procesie, że będzie to pre-dirty check, a tym samym zachowanie, które chcesz.

0

Dla mnie wygląda na naruszenie specyfikacji. A może to zbyt mocne sformułowanie, lepiej chyba powiedzieć, że taki narożny przypadek nie jest wystarczająco jasno określony. JPA 1.0 (Hibernate 3.2.7 jest jednym z wdrożeń) Specyfikacja czary dość wyraźnie kiedy wersja powinna być aktualizowana:

Atrybut wersja jest aktualizowana przez program dostawcy wytrwałość gdy obiekt jest zapisywany w bazie danych.

ustawienie również podstawowe cechy w wywoływanego jednostką głos (JPA 2.0): Metoda zwrotna

cyklu życia może zmienić stan niż związek o podmiotu, na który jest wywoływany.

Powiązane problemy