2014-12-08 12 views
9

Sto usando Spring with Hibernate. Sono in esecuzione di test JUnit in questo modo:OptimisticLockException in blocco pessimistico

String number = invoiceNumberService.nextInvoiceNumber(); 

e il metodo invoiceNumberService è:

InvoiceNumber invoiceNumber = invoiceNumberRepository.findOne(1L); 

Sta usando metodo semplice repository di dati di primavera, e sta funzionando bene. Ma quando ho sovrascrivere questo metodo per utilizzare il blocco:

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

sto ottenendo "javax.persistence.OptimisticLockException: Riga è stata aggiornata o cancellata da un'altra transazione"

non riesco a capire il motivo per cui la sua eccezione di blocco ottimistico , mentre sto usando il blocco pessimistico? E dov'è questa parte quando un'altra transazione sta cambiando questa entità? Ho già analizzato molte domande simili e sono piuttosto disperata per questo. Grazie per qualsiasi aiuto

Soluzione:
Il problema era nella mia funzione init nella classe di test:

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

C'era mancanza di

em.flush(); 

che salva i dati nel database , quindi findOne() può ora recuperarlo

+0

Mi sono imbattuto nello stesso problema e nella stessa soluzione. Sembra un bug per me che Hibernate non si svuota da solo. – gnomie

risposta

0

Ques zione: hai fornito l'annotazione @transcational in livello dao o servizio? succede perché due transazioni tentano contemporaneamente di modificare i dati della stessa tabella ... Quindi se rimuovi tutte le annotazioni dal livello dao e inserisci il livello di servizio dovrebbe risolvere il problema in questo modo ... perché io affrontato un simile tipo di problema Spero che aiuti.

+0

Hai letto la domanda da cima a fondo? OP ha erroneamente inserito la risposta nella domanda stessa anziché come risposta. – BalusC

0

Solo per il gusto di pubblicare posterò quanto segue, se qualcuno non è d'accordo, correggimi. In generale in java si consiglia di utilizzare Spring/hibernate e JPA. Hibernate implementa JPA quindi avrai bisogno di dipendenze per Spring e Hibernate.

Successivamente lasciare che Spring/hibernate gestisca le transazioni e la parte di commit. È una cattiva pratica svuotare/impegnare i dati da soli.

Per esempio lasciare che assume il seguente metodo:

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

Nulla accadrà dopo questo metodo (si potrebbe chiamare unire e commit). Ma se lo annoti con @Transactional, la tua entità sarà gestita e alla fine del metodo @Transactional Spring/hibernate impegna le tue modifiche. Questo è sufficiente:

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

Non c'è bisogno di chiamare a filo, Spring/Hibernate gestirà tutto il casino per voi. Non dimenticare che i test devono chiamare i metodi @Transactional o devono essere @Transactional stessi.