# JPA Transaction



## rmacher (19. Feb 2014)

Hallo allerseits

Folgendes (etwas vereinfachtes) Szenario:

Habe die Entity-Klasse _Person _, die wiederum eine Entity-Klasse _Adresse _hat. Eine separate Klasse ist für das Speichern, Löschen, Updaten etc. von Person-Entities zuständig:


```
public void save(Person person) throws Exception {

		if (person.getId() != null && person.getId().intValue() > 0) {
			update(person);
		} else {
			EntityManager em = HelperClass.createEntityManager();

		
			Adresse a = person.getAdresse();

			em.getTransaction().begin();

			if (a.getId() == null) {
				em.persist(a);
			} else {
				em.merge(a);
			}

			em.persist(person);

			try {
				em.getTransaction().commit();
			} catch (Exception e) {
				logger.error(
						"Fehler ... ", e);

				if (em.getTransaction().isActive()) {
					em.getTransaction().rollback();
				}

				throw e;

			} finally {
				if (em.isOpen()) {
					em.close();
				}
			}

		}

	}
```

Nun, habe ich eine weitere Entity-Klasse namens _Firma_, die wiederum unter anderen Referenzen auch eine Kontaktperson vom Typ _Person _hat. Eine separate Klasse ist auch hier für das Speichern, Updaten und Löschen von firma-Instanzen zuständig. Wenn ich jetzt Firma-Entity speichere, muss ich auch Person-Entity speichern (auf CASCADE habe ich verzichtet). Und, ich möchte ein *rollback* machen können, falls etws schief geht. Da meine sava-Methode in der Person-Persister Klasse einen eigenen EntityManager hat, Transaction startet und die Änderungen commitet, eignet sich diese beim Speichern der Firma-Entity nicht, da ich damit ein *rollback *evtl. nicht mehr machen kann. Heisst, ich muss den ganzen Code noch einmal in der Firma-Persister klasse implementeiren . Oder, in ich habe in der Person-Persister Klasse (oder einer anderen Helper-Klasse) die save-Methode, welche die Person-Entity speichert, jedoch ohne *commit *auszuführen. Dazu würde ich beim Aufruf dieser Methode den EntityManager übergeben, mit dem ich die Transaktion gestartet und auch am Schluss commiten werde. Sollte etwas irgendeinmal innerhalb dieser Transaction schief gehen, kann ich so problemloss ein *rollback *machen. 

Nun finde ich das nicht schön: redundanter Code etc. Und, auf die Verwendung eines EntityManager auf der Application-Ebene würde ich auch gerne verzichten. 

Gibt es da eine bessere Möglichkeit, das Problem zu lösen? Könnte ich evtl. in der save-Methode der Person-Persister abfragen, ob eine Transaction schon aktiv ist und falls ja, würde ich diese nutzen (die Frage ist aber auch, wie ich auf die EntityManager-Instanz kommen würde), und fall nicht, würde ich eine neue Transaction starten, nachdem ich zuerst einen neuen EntityManager erstellt habe?

Danke für jeden Typ.

*Hinweis:*
Es handelt sich um eine JavaSE Anwendung:

[XML]<persistence-unit name="mypu" transaction-type="RESOURCE_LOCAL">[/XML]


----------



## fischefr (21. Feb 2014)

Ich würde das commiten aus dem save rausziehen. Evtl. wäre auch Spring ein geeignetes Framework, um deine Transaktionen besser managen zu können. Ich kenne dein genaues Szenario nicht, aber normalerweise läuft das z.B. bei Client-Server-Anwendungen so:

1. Request kommt vom Client
2. Server eröffnet DB-Transaktion
3. Server arbeitet Anfrage ab (diverse Methodenaufrufe etc.)
4. Server committet Transaktion
5. Rücksprung


----------



## rmacher (25. Feb 2014)

Vielen Dank.

Ich habe das Problem jetzt so gelöst, dass ich für jede entity zwei "Persister-Klassen" implementiert habe. Folgender Code zeigt es exemplarisch:


```
public class AdressePersister {

	public void save(Adresse adresse) throws Exception {

		if (adresse.getId() != null) {
			throw new PersisterException(" ... message ...");
		} else {
			EntityManager em = HelperClass.createEntityManager();
			em.getTransaction().beginn();
			
			AdressePersisterUtil.save(adresse, em);
			
			try {
				em.getTransaction().commit();
			} catch (Exception) {
				logger.error(" ... message ...");
				
				if (em.getTransaction().isActive()) {
					em.getTransaction().rollback();
				}

				throw e;
			} finally {
				if (em.isOpen()){
					em.close();
				}
			}
		}
	}
	
	// weitere Methoden ...

	
}
```

Die Klasse _AdressePersisterUtil _sieht wie folgt aus:

```
public class AdressePersisterUtil {

	public static void save(Adresse adresse, EntityManager em) throws Exception {
	
		Ort ort = adresse.getOrt();
		
		if (ort.getId() != null) {
			OrtPersisterUtil.update(ort, em);
		} else {
			OrtPersisterUtil.save(ort, em);
		}
	
		em.persist(adresse);
	}
	
	// weitere Methoden (update / delete ...)
	
}
```

Für die Entity _Ort _gibt es auch zwei Klassen (_OrtPersister _und _OrtPersisterUtil_), die ähnlich wie _AdressePersister _und _AdressePersisterUtil _ aufgebaut sind und funktionieren. In deder xxxPersistetUtil-Klasse sind Klassenmethoden, die an einer schon bestehenden Transaktion teilnehmen können. Wenn ich jetzt Adresse als Bestandteil einer Person-Entity behandeln muss, kann ich die AdressePersisterUtil-Methoden save bzw. update verwenden. Bevor ich sie aufrufe, wird ein EntityManager erstellt und die Transaktion gestartet. Wenn etwas schief geht, kann ich in der Aufrufer-Methode problemlos ein *rollback *machen, da keine der aufgerufenen Methoden ein *commit *gemacht hat.

Bei diesem Ansatz hält sich die Coderedundanz im Rahmen, da z.B. in der _AdressePersister.save_ Methode die Methode _AdressePersisterUtil.save_ aufgerufen wird. Jedoch gibt es etwas mehr Methodenaufrufe, was sich evtl. auf die Performance negativ auswirken könnte. 

Ich hoffe, dass ich mit diesem Ansatz einigermassen richtig liege und bin für weitere Tipps dankbar.


----------

