2014-12-08 9 views
9

Ich verwende Spring mit Hibernate. Ich bin mit JUnit-Test wie folgt aus:OptimisticLockException in pessimistischen Sperren

String number = invoiceNumberService.nextInvoiceNumber(); 

und invoiceNumberService Methode ist:

InvoiceNumber invoiceNumber = invoiceNumberRepository.findOne(1L); 

es einfache Feder-Daten-Repository-Methode verwendet, und es funktioniert gut. Aber wenn ich diese Methode überschreiben Verriegelung zu verwenden:

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

Ich erhalte „javax.persistence.OptimisticLockException: Row aktualisiert wurde oder durch eine andere Transaktion gelöscht“

Ich kann nicht verstehen, warum seine optimistische Sperre Ausnahme , während ich pessimistische Verriegelung verwende? Und wo ist dieser Teil, wenn eine andere Transaktion diese Entität ändert? Ich habe schon viele ähnliche Fragen und ich bin ziemlich verzweifelt darüber. Vielen Dank für jede Hilfe

Lösung:
Das Problem war in meiner Funktion init in Testklasse:

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

Es war der Mangel an

em.flush(); 

, die die Daten in der Datenbank speichert , so dass findOne() es jetzt retreive

+0

Ich stieß auf das gleiche Problem und die gleiche Lösung. Klingt für mich wie ein Fehler, dass Hibernate nicht selbst flutet. – gnomie

Antwort

0

Ques tion: Haben Sie die @transcational Annotation in dao oder service layer angegeben? es geschieht aus dem Grund, dass zwei Transaktionen gleichzeitig versuchen, die Daten der gleichen Tabelle zu ändern..So wenn Sie alle Annotation von der Dao-Ebene entfernen und in die Service-Schicht einfügen, sollte es das Problem lösen i this..because konfrontiert ähnliche Art von Problem. Hoffe es hilft.

+0

Haben Sie die Frage von oben nach unten gelesen? OP hat die Antwort fälschlicherweise in der Frage selbst gepostet anstatt als Antwort. – BalusC

0

Nur um es zu tun werde ich die folgenden, wenn jemand widerspricht bitte korrigieren Sie mich. Im Allgemeinen wird in Java empfohlen, Spring/Hibernate und JPA zu verwenden. Hibernate implementiert JPA, sodass Sie Abhängigkeiten für Spring und Hibernate benötigen.

Lassen Sie Spring/Hibernate Ihre Transaktionen und den Committeil verwalten. Es ist eine schlechte Übung, Ihre Daten selbst zu spülen/zu übertragen.

Zum Beispiel lassen Sie die folgende Methode übernehmen:

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

Nichts nach dieser Methode passieren wird (könnte man nennen verschmelzen und begehen). Wenn Sie es jedoch mit @Transactional annotieren, wird Ihre Entität verwaltet und am Ende der @ Transactional-Methode werden Spring/Hibernate Ihre Änderungen festschreiben. Also das ist genug:

Keine Notwendigkeit, flush, Spring/Hibernate wird die ganze Unordnung für Sie behandeln. Vergessen Sie nicht, dass Ihre Tests @Transactional-Methoden aufrufen müssen oder selbst @Transactional sein sollten.