Warp 1.0 – beschleunigen!

Bereitstellung und Verwaltung des Persistenzkontexts

Da nun die Verwaltung des Persistenzkontexts durch Warp übernommen wird, vereinfacht sich das obige Beispiel bereits deutlich (Listing 3).

Listing 3 « Definition eines PersistenceService »
@Inject
private Provider entityManagerProvider;

public void persistBrand(Brand brand) {
  EntityTransaction transaction = entityManagerProvider.get().getTransaction();
  transaction.begin();
  try {
    entityManager.persist(brand);
    transaction.commit();
  } catch (Throwable e) {
    transaction.rollback();
    throw new RuntimeException(e);
  } 
}

Hier wird mittels eines Provider<EntityManager> ein Persistenzkontext zur Verfügung gestellt, der nun nicht mehr vom Anwendungsentwickler geschlossen werden muss. Bei Verwendung von Hibernate würde hier ein Provider<Session>, im Falle von db4o ein Provider<ObjectContainer> verwendet. Es wurde also nicht versucht, ein einheitliches Interface für die verschiedenen Persistenzkontexte zu schaffen. Stattdessen programmiert der Anwendungsentwickler weiterhin gegen die bekannte Schnittstelle.

Transaktionsabgrenzung durch @Transactional

Das zweite wesentliche Ziel zur Vereinfachung von JPA stellt die Deklaration von Transaktionsgrenzen dar. Wenig überraschend, dass Warp-persist hier den von ähnlichen Frameworks bekannten Weg der Auszeichnung von Methoden mit einer eigenen Annotation geht. Daraus ergibt sich eine weitere Vereinfachung des Beispiels (Listing 4).

Listing 4 « Speichern einer Entität mittels Warp-persist »
@Inject
private Provider entityManagerProvider;

@Transactional
public void persistBrand(final Brand brand) {
  entityManagerProvider.get().persist(brand);
}

Somit wird vor Ausführung der Methode eine Transaktion gestartet und nach erfolgreicher Abarbeitung durch ein commit abgeschlossen. Wurde bereits eine Transaktion in diesem Persistenzkontext gestartet, so wird diese Methode an der laufenden Transaktion teilnehmen. Erfolgreiche Abarbeitung heißt hier, dass bei Ausführung der Methode keine RuntimeException geworfen wurde. Im Gegensatz zu ähnlichen Frameworks lässt sich hier allerdings mithilfe der Parameter rollbackOn und exceptOn genauer definieren, in welchen Fällen ein Rollback erfolgen muss. RollbackOn definiert hierbei die Exception, bei der ein Rollback erfolgt, exceptOn sorgt dafür, dass die gennante Exception von der Regel ausgenommen wird.

@Transactional(rollbackOn = Throwable.class, exceptOn = MyException.class)
public void doSomething() throws MyException, MyFatalException {
  // ...
}

Im obigen Beispiel wird demnach bei allen Throwables, ausgenommen Instanzen der Klasse MyException bzw. deren Subklassen, ein Rollback ausgelöst. Alternativ zur Auszeichnung einzelner Methoden kann auch eine Klasse mit @Transactional ausgezeichnet werden. Hier dient dann die Auszeichnung der Klasse als Voreinstellung für die Methoden, die jedoch ggf. wieder überschrieben werden kann. Gerade im Fall von DAO-Klassen erspart dies zusätzlich etwas Tipparbeit, macht aber notwendig, dass die entsprechenden Klassen dem PersistenceService bekannt gemacht werden (Listing 5).

Listing 5 « Verwendung von @Transactional auf Klassen »
    bindConstant().annotatedWith(JpaUnit.class).to("example");
    TransactionStrategyBuilder tsb =     PersistenceService.usingJpa().across(UnitOfWork.TRANSACTION);
    
    // Anmeldung aller Klassen, die mit @Transactional ausgezeichnet sind.
    PersistenceModuleBuilder pmb =     tsb.forAll(Matchers.annotatedWith(Transactional.class), Matchers.any()); 
    install(pmb.buildModule());
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.