Transakcja oznaczona jako rollbackOnly

Transakcja oznaczona jako rollbackOnly, jak sama nazwa mówi, jest przeznaczona tylko do wycofania. Czyli po zakończeniu przebiegu wszystkich operacji w ramach transakcji, nie jest wykonywana operacja commit (zatwierdzenie) tylko rollback (wycofanie).

Po co jakaś flaga, skoro mamy już mechanizm obsługi transakcji w bazach danych?

W tradycyjnej transakcji mamy najczęściej taką sytuację:

BAZA DANYCH: OTWÓRZ TRANSAKCJE
BAZA DANYCH: WYKONAJ OPERACJE A
BAZA DANYCH: WYKONAJ OPERACJE B
BAZA DANYCH: WYKONAJ COMMIT LUB ROLLBACK (W ZALEŻNOŚCI OD TEGO CZY PO DRODZE BYŁY JAKIEŚ PROBLEMY CZY TEŻ NIE)

Ale już w świecie programowania webowego mamy jeszcze różnego rodzaju kod wykonujący się pomiędzy operacjami schodzącymi do bazy danych:

BAZA DANYCH: OTWÓRZ TRANSAKCJE
JAVA       : WYKONAJ POLECENIE A
BAZA DANYCH: WYKONAJ OPERACJE A
JAVA       : WYKONAJ POLECENIE B
BAZA DANYCH: WYKONAJ OPERACJE B
JAVA       : WYKONAJ POLECENIE C
BAZA DANYCH: WYKONAJ COMMIT LUB ROLLBACK (W ZALEŻNOŚCI OD TEGO CZY PO DRODZE BYŁY JAKIEŚ PROBLEMY CZY TEŻ NIE)

A tak naprawdę, to kod serwera wywołuje operacje bazy danych:

JAVA -> BAZA DANYCH: OTWÓRZ TRANSAKCJE
JAVA               : WYKONAJ POLECENIE A
JAVA -> BAZA DANYCH: WYKONAJ OPERACJE A
JAVA               : WYKONAJ POLECENIE B
JAVA -> BAZA DANYCH: WYKONAJ OPERACJE B
JAVA               : WYKONAJ POLECENIE C
JAVA -> BAZA DANYCH: WYKONAJ COMMIT LUB ROLLBACK (W ZALEŻNOŚCI OD TEGO CZY PO DRODZE BYŁY JAKIEŚ PROBLEMY CZY TEŻ NIE)

I z racji tego, że każdy element kodu może rzucić wyjątek (niezależnie czy wołamy bazę danych czy nie), to potrzebna jest flaga obsługująca całą transakcję, żeby na ostatnim kroku wiedzieć czy należy zatwierdzić (commit) czy też wycofać (rollback) transakcję. Czyli jeśli na dowolnym kroku wystąpi wyjątek, to transakcja jest oznaczana jako rollbackOnly (co powoduje wycofanie transakcji w ostatnim kroku.