2014-12-08 13 views
9

Używam Spring with Hibernate. Używam testów JUnit tak:OptimisticLockException w pesymistycznym blokowaniu

String number = invoiceNumberService.nextInvoiceNumber(); 

i sposób invoiceNumberService jest:

InvoiceNumber invoiceNumber = invoiceNumberRepository.findOne(1L); 

to przy użyciu prostej metody repozytorium danych wiosna, i to działa dobrze. Ale kiedy zastąpić tę metodę do korzystania blokowania:

@Lock(LockModeType.PESSIMISTIC_READ) 
@Override 
InvoiceNumber findOne(Long id); 

Dostaję „javax.persistence.OptimisticLockException: Wiersz został zaktualizowany lub usunięty przez inną transakcję”

Nie mogę zrozumieć, dlaczego jego optymistyczne wyjątek blokady , podczas gdy używam pesymistycznego blokowania? A gdzie jest ta część, gdy inna transakcja zmienia ten podmiot? Mam już kopać wiele podobnych pytań i jestem bardzo zdesperowany na ten temat. Dzięki za wszelką pomoc

Rozwiązanie:
Problem był w mojej funkcji init w klasie testu:

@Before 
public void init() { 
    InvoiceNumber invoiceNumber = new InvoiceNumber(1); 
    em.persist(invoiceNumber); 
    em.flush(); 
} 

Było brak

em.flush(); 

które zapisuje dane do bazy danych , więc findOne() może teraz odzyskać to

+0

Wpadłem na ten sam problem i to samo rozwiązanie. Brzmi jak błąd dla mnie, że Hibernate sam się nie spłukuje. – gnomie

Odpowiedz

0

Pytanie : Czy nadałeś adnotację @transcational w warstwie dao lub serwisie? dzieje się tak dlatego, że dwie transakcje jednocześnie próbują zmienić dane z tej samej tabeli. Tak więc, jeśli usuniesz całą adnotację z warstwy dao i wstawisz warstwę usługi, powinno to rozwiązać problem i dlatego, że napotykał podobny problem. Mam nadzieję, że to pomaga.

+0

Czy czytasz pytanie od góry do dołu? OP omyłkowo opublikował odpowiedź w samym pytaniu zamiast w odpowiedzi. – BalusC

0

Tylko ze względu na to zamieści następującą, jeśli ktoś się nie zgadza, popraw mnie. Ogólnie w java zaleca się używanie Spring/Hibernate i JPA. Hibernate implementuje JPA, więc będziesz potrzebował zależności dla Spring i Hibernate.

Następnie pozwól, aby Spring/Hibernate zarządzały Twoimi transakcjami i zatwierdzaniem części. Złą praktyką jest samodzielne przepłukiwanie/zatwierdzanie danych.

Na przykład niech zakładają następującą metodę:

public void changeName(long id, String newName) { 
    CustomEntity entity = dao.find(id); 
    entity.setName(newName); 
} 

Nic się nie stanie po tej metodzie (można zadzwonić do scalania i popełnienia). Jeśli jednak dodasz adnotację do @Transactional, twoja encja będzie zarządzana i na końcu metody @Transactional Spring/hibernate dokona zmian. Więc to na tyle:

@Transactional 
public void changeName(long id, String newName) { 
    CustomEntity entity = dao.find(id); 
    entity.setName(newName); 
} 

Nie trzeba zadzwonić flush Spring/Hibernate będzie obsługiwać cały bałagan dla Ciebie. Nie zapominajcie, że wasze testy muszą wywoływać metody @Transactional lub same powinny być @Transactional.

Powiązane problemy