Kapitel 49 · JPA Library
Hibernate ORM als JPA Library
JPA Provider mit Lazy Loading, Dirty Checking und Dialekten.
Fachliche Einordnung
Hibernate ORM als JPA Library ist im Enterprise-Kontext kein isoliertes Thema. Es beantwortet die Frage, welche Verantwortung an welcher Stelle im System liegen soll. In einem Order-&-Billing-System entscheidet diese Ebene darueber, ob eine Bestellung nachvollziehbar angenommen, validiert, persistiert, abgerechnet und an Partner- oder Legacy-Systeme weitergegeben werden kann.
Persistenz ist in Enterprise-Systemen selten nur CRUD. Es geht um Aggregatgrenzen, Transaktionslaenge, Lazy Loading, Sperrverhalten, Batchgroessen, Datenbank-Indizes und Nachvollziehbarkeit. Eine gute Jakarta-Architektur verbirgt JPA nicht, aber kapselt sie so, dass Fachlogik nicht von EntityManager-Details dominiert wird.
Technisches Modell
Das wichtigste mentale Modell lautet: API und Implementierung sind getrennt. Jakarta definiert Standards und Annotationen; die konkrete Runtime oder Library liefert das Verhalten. Dadurch kann dieselbe Fachidee auf Open Liberty, WildFly, Payara, TomEE, GlassFish oder in cloud-nativen Frameworks unterschiedlich betrieben werden.
Ausfuehrliches Beispiel
@Entity
@Table(name = "orders")
public class OrderEntity {
@Id private String id;
@Version private long version;
@Enumerated(EnumType.STRING) private OrderStatus status;
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
private List<OrderLineEntity> lines = new ArrayList<>();
protected OrderEntity() { }
public static OrderEntity open(String id, List<OrderLineEntity> lines) {
OrderEntity entity = new OrderEntity();
entity.id = id;
entity.status = OrderStatus.OPEN;
entity.lines.addAll(lines);
return entity;
}
}
@Repository
public interface OrderRepository extends BasicRepository<OrderEntity, String> {
List<OrderEntity> findByStatus(OrderStatus status, Limit limit);
}
@ApplicationScoped
public class JpaOrderStore {
@PersistenceContext EntityManager em;
@Transactional
public void save(OrderEntity entity) {
em.merge(entity); // Pattern: Repository kapselt Persistenzdetails.
}
}
Typische Fehler und bessere Variante
1. Fachlogik im technischen Adapter
Besser: Resource, Servlet oder Listener nur als Adapter nutzen. Die Entscheidung liegt in Application Service und Domain-Modell.
2. Zu breite Transaktion
Besser: Transaktionsgrenzen am Use Case schneiden, externe Calls ausserhalb oder ueber Outbox/JMS entkoppeln.
3. Provider-Magie ohne Dokumentation
Besser: Jede Implementierungsentscheidung in README, ADR oder design-patterns.md vermerken.
4. Keine Betriebsdiagnose
Besser: fachliche IDs, Trace-ID, Health Checks und technische Metriken von Anfang an einbauen.
Praxis-Checkliste
- Typ klar markiert: Spezifikation, Framework, Library, Runtime oder Methodik.
- Codebeispiel trennt Adapter, Application Service, Domain und Infrastruktur.
- Fehlerfall, Security und Transaktion sind erkennbar.
- Migration von Java EE zu Jakarta EE wurde beachtet.
- Teststrategie mit Unit-, Integration- oder Container-Test ist ableitbar.