2012-02-06 18 views
8

Środowisko:Jak ręcznie ustawić pola @Version za pomocą Hibernate 4?

mam że User podmiot:

@Entity 
public class User implements Serializable { 
    private static final long serialVersionUID = 1L; 

    @Id 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private Integer userId; 

    @Version 
    @Temporal(TemporalType.TIMESTAMP) 
    @Column(name = "VERSION", length = 19) 
    private Date version; 

    @Column(nullable = false, length = 20) 
    private String login; 

    // Getters and Setters 
} 

Mam stronę wyszukiwania, która zawiera listę użytkowników, a następnie klikam na użytkownika, aby go edytować (podając userId w adresie URL).

W formularzu edycji, przechowywać na serwerze dziedziny tego podmiotu i kiedy mogę zapisać Użytkownika zrobić to:

User user = entityManager.find(User.class, userId) 
user.setLogin(form.getLogin()); 
user.setVersion(form.getVersion()); 
user.setUserId(form.getUserId()); 
entityManager.merge(user); 

Pytanie:

Więc jeśli dobrze zrozumiałam optymistyczne blokowanie przy użyciu Hibernacji, jeśli otworzę 2 zakładki w przeglądarce, aby edytować tego samego użytkownika, , następnie zaktualizuję logowanie na pierwszej karcie, a następnie , a następnie logowania na drugiej zakładce. Powinienem mieć numer OptimisticLockException. czyż nie ja?

W rzeczywistości nie ma to miejsca w mojej aplikacji ... Zweryfikowałem, że form.getVersion() zwraca tę samą wartość w obu przypadkach, nawet jeśli w drugiej aktualizacji, user.version została zaktualizowana przez pierwszą edycję.

Czy brakuje mi czegoś?

Urządzenie EntityManager jest produkowane @RequestScoped (więc jestem na dwóch różnych EntityManager s, gdy próbuję scalić ...).

Próbowałem zrobić entityManager.lock(user, LockModeType.OPTIMISTIC_FORCE_INCREMENT) przed entityManager.merge(...) (as said here), ale to nie pomogło.

Używam Seam 3 z JBoss 7.0.2.Final (który używa Hibernate 4).

+0

Czy jesteś pewien, że obiekt entityManager jest opróżniany (lub transakcja jest zatwierdzona)? Jakie jest wygenerowane zapytanie o aktualizację SQL? –

+0

Tak, z [aktywacją wyładowania SQL przez Hibernate] (http://stackoverflow.com/questions/9159752/how-to-get-jdbc-binding-parameters-from-hibernate-in-jboss-7) Widzę aktualizacja SQL i powiązanie pola 'version' JDBC, które nie odpowiada" wersji "ustawionej w' User' w 'WHERE id =? AND version =? '... Opracowałem' FlushInterceptor', który jest wywoływany po tym, jak istnieje moja funkcja 'update' i która wykonuje' entityManager.flush() '. –

Odpowiedz

4

Właściwie znalazłem sposób na zrobienie tego ... ale myślę, że to nie jest naprawdę efektywne (ponieważ jest jeszcze jedno żądanie SELECT).

User user = entityManager.find(User.class, userId) 
user.setLogin(form.getLogin()); 
user.setVersion(form.getVersion()); 
user.setUserId(form.getUserId()); 

entityManager.detach(user); 
entityManager.merge(user); 

Z entityManager.detach(user), hibernacja używa teraz moje setted wartość version zamiast własnej wartości skopiowanej gdzieś ...

5

Właśnie zrobiłem trochę więcej badań na ten temat.

Jest nie może modyfikować pola wersji według specyfikacji JPA:

JPA 2,0 końcowego Spec, sekcja 3.4.2

Jednostka może uzyskać dostęp do stanu wersji pole lub właściwość lub wyeksportuj metodę użycia przez aplikację, aby uzyskać dostęp do wersji, ale nie może modyfikować wartości wersji. Z wyjątkiem wymienionym w sekcji 4.10, tylko dostawca utrwalania może ustawiać lub aktualizować wartość atrybutu wersji w obiekcie.

Uwaga: Sekcja 4.10 dotyczy aktualizacji partii, która ignoruje atrybut wersji.

Powiązane problemy