Manuelle JPA-Transaktion vs. deklaratives @Transactional
Ersetze ausführliche begin/commit/rollback-Blöcke durch eine einzige @Transactional-Annotation.
@PersistenceContext
EntityManager em;
public void transferFunds(Long from, Long to,
BigDecimal amount) {
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Account src = em.find(Account.class, from);
Account dst = em.find(Account.class, to);
src.debit(amount);
dst.credit(amount);
tx.commit();
} catch (Exception e) {
tx.rollback();
throw e;
}
}
@ApplicationScoped
public class AccountService {
@PersistenceContext
EntityManager em;
@Transactional
public void transferFunds(Long from, Long to,
BigDecimal amount) {
var src = em.find(Account.class, from);
var dst = em.find(Account.class, to);
src.debit(amount);
dst.credit(amount);
}
}
Kein Boilerplate
Eine einzige Annotation ersetzt sich wiederholende begin/commit/rollback-try-catch-Blöcke.
Sichereres Rollback
Der Container garantiert Rollback bei ungeprüften Exceptions — kein Risiko, den catch-Block zu vergessen.
Deklarative Steuerung
Propagation, Isolation und Rollback-Regeln werden als Annotationsattribute ausgedrückt.
Weitgehend verfügbar seit Jakarta EE 8 / Java 11
Manuelle Transaktionsverwaltung erfordert explizite begin()-, commit()- und rollback()-Aufrufe, die in try-catch-Blöcke eingebettet sind — jede Service-Methode wiederholt diesen Boilerplate. Die @Transactional-Annotation delegiert das Lebenszyklusmanagement an den Container — er startet vor der Methode eine Transaktion, bestätigt bei Erfolg und führt bei RuntimeException automatisch ein Rollback durch.