2017-10-18 90 views
5

Znalazłem wiele postów dotyczących tego tematu, ale wszystkie odpowiedzi były po prostu linkami do dokumentacji bez przykładowego kodu, tj. Jak używać współbieżności w praktyce.Współbieżność z Hibernacja na wiosnę

Moja sytuacja: Mam podmiot House z (na simplyfication) dwóch atrybutów, number (ID) i owner. Baza danych jest inicjowana 10 Houses z number 1-10 i owner zawsze null.

Chcę przypisać nowego właściciela do domu, w którym nie ma właściciela, a najmniejszego number. Mój kod wygląda następująco:

@Transactional 
void assignNewOwner(String newOwner) { 
    //this is flagged as @Transactional too 
    House tmp = houseDao.getHouseWithoutOwnerAndSmallestNumber(); 

    tmp.setOwner(newOwner); 

    //this is flagged as @Transactional too 
    houseDao.update(tmp); 
} 

Dla mojego zrozumienia, chociaż @Transactional stosowany jest ten sam House mogłyby być przypisane dwa razy do różnych właścicieli, jeśli dwa wnioski sprowadzić ten sam pusty House jak tmp. Jak mogę się upewnić, że tak się nie stanie?

Wiem, w tym aktualizacja w wyborze pustego House rozwiąże problem, ale w niedalekiej przyszłości chcę zmodyfikować/pracować z obiektem tmp więcej.

+1

'' houseDao.update (tmp); 'jest niepotrzebne, ponieważ' tmp' jest jednostką zarządzaną (jesteś w metodzie transakcyjnej). Zmiany będą zachowane bez potrzeby osobnego 'update()'. – Kayaman

Odpowiedz

1

Optymistyczne

Jeśli dodać kolumnę wersji do podmiotu/stół wtedy można skorzystać z mechanizmu zwanego Optymistyczne blokującego. Jest to najbardziej sprawny sposób upewnienia się, że stan podmiotu nie zmienił się od momentu, w którym uzyskaliśmy go w kontekście transakcyjnym.

Po createQuery pomocą session można następnie wywołać setLockMode(LockModeType.OPTIMISTIC);

Potem, tuż przed transakcja jest przyznaniem, dostawca wytrwałość by zapytać o bieżącej wersji tego podmiotu i sprawdzić, czy został on zwiększony o innej transakcji . Jeśli tak, otrzymasz wyjątek OptimisticLockException i wycofanie transakcji.

Pesymistyczny

Jeśli nie wersję swoich wierszy, potem w lewo z pesymistycznym lockin które w zasadzie oznacza, że ​​phycically stworzyć blokadę dla zapytań podmiotów na poziomie bazy danych i innych transakcji nie może odczytać/aktualizować te niektóre wiersze.

to osiągnąć przez ustawienie tego na obiekcie Query:

setLockMode(LockModeType.PESSIMISTIC_READ);

lub

setLockMode(LockModeType.PESSIMISTIC_WRITE);

1

Właściwie to całkiem proste - przynajmniej moim zdaniem i mam zamiar streszczenie z dala od tego, co Hibernate wygeneruje, gdy powiesz Pessimistic/Optimistic. Możesz myśleć, że to jest SELECT FOR UPDATE - ale nie zawsze tak jest, MSAQL AFAIK nie ma tego ...

Są to adnotacje o numerach JPA i gwarantują pewną funkcjonalność, a nie implementację.

Zasadniczo są to różne rzeczy - PESSIMISTIC vs OPTIMISTIC blokowanie. Kiedy robisz pesymistyczne zamknięcie, przynajmniej w sensie logicznym, możesz robić co tylko chcesz i jesteś bezpieczny w ramach transakcji. Teraz, niezależnie od tego, jaki blokada jest przechowywana dla row, table or even page jest nieokreślona; więc trochę niebezpieczne. Zwykle baza danych może eskalować blokady, MSSQL robi to, jeśli ponownie wezwę poprawnie.

Oczywiście blokowanie głodzenia jest problemem, więc możesz pomyśleć, że blokowanie OPTIMISTIC może pomóc. Na marginesie, to jest to, co transactional memory is in modern CPU; używają tego samego procesu myślenia.

Optymalne blokowanie jest jak mówienie - zaznaczę ten wiersz identyfikatorem/datą, itd., Wtedy zrobię migawkę tego i popracuję nad nim - przed wykonaniem sprawdzę, czy ten identyfikator został zmieniony. Oczywiście jest spór na temat tego ID, ale nie na danych. Jeśli uległo zmianie - przerwij (alias rzut OptimisticLockException) w przeciwnym razie popełnij błąd.

Rzeczą, która nurtuje wszystkich IMO, jest to, że OptimisticLockException - jak odzyskać od tego? A tutaj jest coś, czego nie polubisz - to zależy od. Istnieją aplikacje, w których wystarczy zwykła próba, są aplikacje, w których byłoby to niemożliwe. Używałem go w rzadkich sytuacjach.

Zazwyczaj używam blokady Pessimistic (chyba, że ​​Optimistic nie jest opcją). W tym samym czasie będę wyglądać, co hibernacji generuje dla tego zapytania. Na przykład możesz potrzebować index, w jaki sposób wpis jest pobierany dla DB, aby rzeczywiście zablokować tylko wiersz - ponieważ ostatecznie tego właśnie chcesz.