07 lutego 2007

Java Persistence - 3.3 Żywotność kontekstu utrwalania

Udało mi się znaleźć kolejne dobre (lepsze?) tłumaczenie dla słowa lifecycle, czyli po polsku istnienie. Na pierwszy rzut oka nie wydaje się być trafne, ale w niektórych sformułowaniach bardzo dobrze się komponuje i wydaje się być dobrą alternatywą dla cyklu życia. Zresztą w relacji z lektury rozdziału 3.3 Żywotność kontekstu utrwalania skorzystałem z tego skrzętnie.

Żywotność kontekstu utrwalania zarządzanego przez kontener/serwer aplikacyjny (ang. container-managed persistence context) może być ograniczona do transakcji (ang. transaction-scoped persistence context) lub trwać znacznie dłużej (ang. extended persistence context).

Typ wyliczeniowy - javax.persistence.PersistenceContextType - służy do określenia długości życia kontekstu utrwalania zarządzanego przez kontener. Długość życia kontekstu określana jest w momencie utworzenia instancji EntityManager (wprost poprzez konstruktor, poprzez wstrzelenie zależności czy wyszukanie w drzewie JNDI).

Typ wyliczeniowy PersistenceContextType dostarcza dwóch wartości określających rodzaj kontekstu utrwalania:
  • EXTENDED - określa, że żywotność kontekstu jest przedłużona, tj. trwająca dłużej niż pojedyńcza transakcja
  • TRANSACTION - (domyślna) określa, że żywotność kontekstu związana jest z pojedyńczą transakcją
Użycie kontekstu utrwalania zarządzanego przez kontener w trybie przedłużonej żywotności powoduje, że jego istnienie rozpoczyna się w momencie utworzenia instancji EntityManager i kończy podczas jego zamknięcia (wynik operacji close). Tak zdefiniowany kontekst może być związany z wieloma transakcyjnymi i nietransakcyjnymi operacjami instancji EntityManager. Przedłużony kontekst przyłącza się do aktywnej transakcji, kiedy metody EntityManager'a bądź stanowego komponentu sesyjnego (SFSB), z którym kontekst jest związany, są wywołane w jej zasięgu (to podpowiada możliwe zastosowanie przedłużonego kontekstu, gdzie wykonanie metody transakcyjnej nie powinno zatwierdzać modyfikacji do bazy danych przy zakończeniu metody, a tym samym i możliwym zakończeniu transakcji, np. stanowy komponent reprezentujący koszyk).

EntityManager z przedłużonym kontekstem utrwalania utrzymuje referencje instancji encji po zatwierdzeniu transakcji. Instancje encji są nadal zarządzane i mogą podlegać modyfikacją nawet pomiędzy transakcjami. W takim trybie pracy kontekstu encje nie są przeładowywane (odświeżane) przy każdorazowym rozpoczęciu transakcji. Bez względu na istnienie transakcji, nawigacja po polach/właściwościach relacyjnych (korzystanie z encji zależnych, będących w relacji) powoduje powołanie encji zarządzanych (tak jakby transakcja była wciąż aktywna mimo, że nie musi).

Użycie EntityManager z przedłużonym kontekstem utrwalania zarządzanym przez kontener zdejmuje konieczność istnienia aktywnej transakcji podczas wywoływania operacji persist, remove, merge i refresh. Wynik ich działania będzie zapisany w bazie danych w momencie zatwierdzenia transakcji, do której przyłączył się przedłużony kontekst utrwalania.

Żywotność kontekstu utrwalania zarządzanego przez aplikację (lub inaczej związanego z EntityManager'em, który zarządzany jest przez aplikację - ang. application-managed entity manager) jest przedłużona. Po stronie aplikacji leży odpowiedzialność za zarządzanie istnieniem kontekstu utrwalania.

Więcej informacji o przedłużonym kontekście utrwalania znajduje się w sekcji 5.7 (oj, to wieki miną zanim się za niego zabiorę! Autorzy specyfikacji wydaje się, że zdawali sobie z tego sprawę przybliżając temat przedłużonego kontekstu już teraz).

Zatwierdzanie transakcji

Zatwierdzenie transakcji zmienia stan encji zarządzanych w kontekście utrwalania ograniczonym do transakcji na odłączony, a w przedłużonym pozostają zarządzane.

Wycofanie transakcji

Bez względu na rodzaj kontekstu utrwalania, wycofanie transakcji powoduje, że wszystkie encje posiadające trwały stan (tj. posiadają swój odpowiednik w bazie danych) zanim rozpoczęła się wycofywana transakcja oraz encje skasowane staną się odłączone. Stan instancji encji będzie stanem instancji w momencie wycofania transakcji. Zazwyczaj wycofanie transakcji powoduje, że kontekst utrwalania będzie w nieokreślonym stanie (stan atrybutów wersjonujących i stan tworzony automatycznie - generowane klucze główne) mogą być niespójne. Encje, które były poprzednio zarządzane (włączając encje nowe i utrwalone w wycofywanej transakcji) mogą być bezużyteczne (w porównaniu z innymi odłączonymi encjami) i operacja merge na nich może zakończyć się błędem (specyfikacja nie określa stanu nowych encji, jeszcze nie utrwalonych w bazie, a po wycofaniu transakcji - czy są one nadal nowe czy już odłączone).

Krótko, zwięźle i na temat, ale myliłby się ten, kto uważa, że wszystko już zostało na temat przedłużonych kontekstów utrwalania powiedziane. Więcej w sekcji 5.7. Zmierzam ku sekcji 3.4 Optimistic Locking and Concurrency.