2016-09-27 24 views
10

Mam problem ze współbieżnością, którą próbowałem rozwiązać za pomocą pętli while, która próbuje zapisać obiekt kilka razy, aż osiągnie maksymalną liczbę ponownych prób. Chciałbym uniknąć mówienia o tym, czy istnieją inne sposoby rozwiązania tego problemu. Mam inne posty Stackoverflow na ten temat. :) Long story short: istnieje unikalne ograniczenie dla kolumny, która jest wyprowadzana i zawiera część liczbową, która zachowuje inkrementację, aby uniknąć kolizji. W pętli I:Wpis współzależności JPA "Po wydaniu wsadu nadal zawierał wyciągi JDBC"

  1. select max (some_value)
  2. przyrost wynikiem
  3. próba zapisać nowy obiekt z nową wyniku
  4. wyraźnie przepłukać podmiotu, a jeśli to się nie uda, ponieważ z unikalny indeks, łapię wyjątek DataAccessException.

Wszystko to wydaje się działać z wyjątkiem gdy pętla wraca do kroku 1 i próbuje wybrać, otrzymuję:

17:20:46,111 INFO [org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl] (http-localhost/127.0.0.1:8080-3) HHH000010: On release of batch it still contained JDBC statements 
17:20:46,111 INFO [my.Class] (http-localhost/127.0.0.1:8080-3) MESSAGE="Failed to save to database. Will retry (retry count now at: 9) Exception: could not execute statement; SQL [n/a]; constraint [SCHEMA_NAME.UNIQUE_CONSTRAINT_NAME]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement" 

A nowy wyjątek zostanie złapany. Wygląda na to, że pierwszy spór, który powoduje wyjątkowe naruszenie ograniczenia i powoduje, że DataAccessException nie powoduje wyczyszczenia partii menedżera encji. Jaki jest odpowiedni sposób, aby sobie z tym poradzić? Używam Springa z JPA i nie mam bezpośredniego dostępu do menedżera encji. Sądzę, że mógłbym wstrzyknąć go, gdybym go potrzebował, ale jest to bolesne rozwiązanie tego problemu.

Odpowiedz

5

Nie możesz tego zrobić - po wypłukaniu czegoś i nie powiedzie się, a wyjątek zostanie zgłoszony, transakcja zostanie oznaczona jako wycofana. Oznacza to, że nie ma znaczenia, że ​​wychwycisz wyjątek i kontynuujesz, skończy się wycofaniem. Właściwie to nie ma znaczenia w ogóle, co wyjątek został wyrzucony - domyślnie menedżer transakcji Spring cofnie każdy wyjątek odznaczony niezaznaczony. Można go pokonać przez specjalnie definiowania noRollbackFor na @Transactional adnotacji (zapewniając używasz transakcji sterownika adnotacja)

Edycja - to też nie pomoże w przypadku tego naruszenia ograniczenia, ponieważ transakcja zostanie prawdopodobnie zaznaczone jako wycofanie na poziomie bazy danych.