JPA - różnice między transakcjami JTA i RESOURCE_LOCAL

0

Witam,
proszę o wyjaśnienie różnic między typam transakcji JTA i RESOURCE_LOCAL.

Według moich informacji wynika, że używając transakcji typu JTA źródło danych musimy skonfigurować na serwerze aplikacyjnym. W pliku persistence.xml podajemy tylko nazwę tego źródła:

<persistence-unit name="zrodlo" transaction-type="JTA">
	<jta-data-source>zrodlo</jta-data-source>
</persistence-unit>

W aplikacji możemy wtedy użyć adnotacji @PersistenceContext aby dostać obiekt managera encji (EntityManager)

Wykorzystując komponenty sesyjne EJB i transakcje JTA nie musimy się martwić o zarządzanie transakcjami, gdyż wszystkie metody komponentu sesyjnego wykonywane są w ramach transakcji. Kiedy w takim razie transakcje są wycofywane?

Przykładowy kod mógłby wyglądać tak:

@Stateless
public class MojBean implements MojLocal {

@PersistenceContext(unitName = "zrodlo")
	EntityManager em;
    
    public void zmien(int id) {
	EncjaJPA encja= em.find(EncjaJPA.class, id);
	encja.setNazwa("Nowa nazwa");
	em.merge(encja);
    }
}

Jeżeli nie kożystamy z EJB musimy samodzielnie zarządzać transakcjami JTA używając do tego interfejsu UserTransaction:

@Resource 
	private UserTransaction ut
@PersistenceContext(unitName = "zrodlo")
	EntityManager em;
//...

ut.begin();
em.jainTransaction();
boolean comitted = false;
try{
	//operacje na obiekcje em
	ut.commit();
	commited = true;
} finally{
if(!comitted)
	ut.rollback();
}

Z kolei jeżeli wykożystujemy transakcje typu RESOURCE_LOCAL źrodło danych możemy skonfigurować na serwerze aplikacyjnym lub bezpośrednio w pliku persistence.xml

W pierwszym przypadku w pliku persistence.xml podajemy tylko nazwę źródła danych np:
<non-jta-data-source>zrodlo</non-jta-data-source>
W kodzie aplikacji aby uzyskać obiekt EntityManagera musimy użyć obiektu EntityManagerFactory, z tego powodu nie możemy użyc adnotacji @PersistenceContext. W celu uzyskania obiektu EntityManagerFactory możemy za to użyć adnotacji @PersistenceUnit.

W drugim przypadku wszystkie dane do połączenia z bazą danych konfigurujemy wewnątrz znacznika <properties> </properties>, ale nie możemy używać żadnych adnotacji w celu uzyskania obiektów EntityManager lub EntityManagerFactory. Dostęp do obiektu EntityManagerFactory możemy uzyskać w następujący sposób
Persistence.createEntityManagerFactory("zrodlo");

W trybie RESOURCE_LOCAL samodzielnie musimy zarządzać transakcjami nawet jeżeli korzystamy z EJB? Robimy to nie poprzez interfejs UserTransaction tylko EntityTransaction, który otrzymujemy poprzez wywołanie metody getTransaction(); na managerze encji np:

EntityManagerFactory emf = Persistence.createEntityManagerFactory("zrodlo");
EntityManager em = createEntityManager();
em.getTransaction().begin();
EncjaJPA encja= em.find(EncjaJPA.class, 1);
encja.setNazwa("Nowa nazwa");
em.merge(encja);
em.getTransaction().commit();
em.close();

Proszę o potwierdzenie, bądź zaprzeczenie tych informacji i ewentualnie podanie dodatkowych informacji o których powinienem wiedzieć.
Pozdrawiam

0

W Przypadku RESOURCE_LOCAL transakcje nie tyle co są zarządzane przez użytkownika, ale zarządzanie może być przekazane do managera, który nie jest zgodny z JTA. Tak robi np. Google Guice JPA Module, które nie jest zgodne z JTA, ale pozwala na m.n. używanie @Transactional.

1

RESOURCE_LOCAL oznacza ze transakcje nie sa za pomoca JTA lecz za pomoca EntityTransaction. Spojrz na EntityManager.getTransaction. Roznica jest taka ze JTA daje Ci rozproszone transakcje, ktore pozwalaja aby wiele zasobow uczestniczylo w jednej. Bez roznicy czy transakcje sa zarzadzane przez kontener (CMT - container manager transactions) czy uzywasz UserTransaction (BMT - bean managed transactions) - uzywasz interejsu JTA ktory jest monitorem transakcji. Gdy uzywasz EntityTransaction to Ty sam zarzadzasz transakcjami, jak w JDBC, uzywasz tylko pewnej cienkiej abstakcji. W kontenerze uzywasz najczesciej CMT, czasami BMT, ale prawie nigdy RESOURCE_LOCAL (przynajmniej z mojego doswiadczenia), no chyba ze specjalnie chcesz aby dany EntityManager nie byl czescia transakcji. Gdzie sie moze przydac? Na szybko przychodzi mi jedno do glowy - logowanie do bazy danych - gdy sie nie uda zapis, nie wplywa to na transakcje JTA; gdy nie uda sie transakcja, zapis logu do bazy i tak leci bo uzywa sie innej transkacji (lokalnej) - gdyby bylo uzywane JTA, to rollback tej transakcji by zrobil rowniez rollback logu, a wlasnie chodzi o to zeby go zapisac w tym momentice.
RESOURCE_LOCAL uzywasz gdy dzialasz z JPA w Java SE, gdzie nie masz / nie potrzebujesz implementacji JTA. Oczywiscie mozesz miec w SE implementacji JPA (Atomikos), pytanie tylko czy tego potrzeba (czasami owszem, najczesciej nie).

0

Czy w trybie Resource_Local transakcje też mogą być zarządzane przez kontener EJB?
Sorry za takie pytania, ale dopiero się uczę.

0

Nie, nie moga. Kontener moze zarzadzac tylko CMT - container managed transactions, ktore uzywaja pod spodem JTA.

0

Użyj Springa:
http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/transaction.html
Dzięki temu będziesz mieć deklaratywne zarządzanie transakcjami zarówno w środowisku serwerowym, jak i w Javie SE.

Co do kwestii wyboru datasource:
-non-jta (w połączeniu z HibernateTransactionManager) - użyj, gdy nie potrzebujesz transakcji rozproszonych
-jta (w połączeniu z JtaTransactionManager) - użyj, gdy transakcje rozproszone są wymagane. Wymaga serwera aplikacji wspierającego JTA lub http://www.atomikos.com lub http://jotm.ow2.org/

1 użytkowników online, w tym zalogowanych: 0, gości: 1