- 1 Section
- 10 Lessons
- unbegrenzt
Repository
Stell dir vor, du gehst in die Bibliothek und willst „Faust I" ausleihen. Du gehst nicht selbst ins Magazin, suchst Regale ab, prüfst die Signaturen und schleppst das Buch durch ein Labyrinth – du sagst dem Bibliothekar einfach: „Ich brauche Faust I.". Er kümmert sich um den Rest. Genau das macht das Repository-Pattern: es ist eine Schicht zwischen deiner Geschäftslogik und der Datenquelle, die das „Wie wird's gespeichert?" komplett verbirgt. Deine Logik fragt kundeRepo.findById(42) – und ob das Repository die Daten aus einer SQL-Datenbank, einer REST-API oder einer Textdatei holt, ist ihm völlig egal. Das Repository-Pattern wurde von Eric Evans im Buch Domain-Driven Design bekannt gemacht und ist heute in fast jeder ernsthaften Backend-Architektur Pflicht.
1) Das Problem, das Repository löst
Ohne Repository sieht typischer Anfängercode etwa so aus: deine Geschäftslogik enthält SQL-Strings, ruft direkt connection.prepareStatement(...) auf, kümmert sich um try-catch-finally, schließt Connections und mappt das ResultSet manuell auf ein Objekt. Das Ergebnis: deine Geschäftslogik ist verwoben mit Datenbankcode. Drei Probleme:
❌ Ohne Repository
Geschäftslogik kennt SQL. Test ohne echte DB unmöglich.
void rabattGeben(int id) {
ResultSet rs = conn.prepareStatement(
"SELECT * FROM kunden WHERE id=?")
.executeQuery();
if (rs.getInt("umsatz") > 1000)
conn.prepareStatement(
"UPDATE kunden SET rabatt=10 ...")
.executeUpdate();
}
✓ Mit Repository
Logik kennt nur Objekte. Test mit Fake-Repo einfach.
void rabattGeben(int id) {
Kunde k = kundeRepo.findById(id);
if (k.getUmsatz() > 1000) {
k.setRabatt(10);
kundeRepo.save(k);
}
}
Die zweite Variante ist nicht nur kürzer – sie ist auch testbar ohne Datenbank: in einem Unit-Test ersetzt du kundeRepo durch eine Fake-Implementierung, die Daten aus einer HashMap holt. Mehr dazu siehst du in Unit-Tests aufbauen.
2) Datenquelle wechseln – ohne Logik anzufassen
Der größte Wert von Repository: du kannst die Datenquelle austauschen, ohne die Geschäftslogik anzufassen. Klick unten auf die verschiedenen Datenquellen – die obere Schicht (Service) bleibt jedes Mal exakt gleich:
📋 BestellService (Geschäftslogik)
🔌 KundeRepository <Interface>
3) Code zum Beispiel
So sieht eine typische Repository-Struktur in Java aus: ein Interface, das die Operationen definiert, und beliebig viele Implementierungen. Die Geschäftslogik bekommt nur das Interface in die Hand:
public interface KundeRepository { Optional<Kunde> findById(long id); List<Kunde> findAll(); Kunde save(Kunde k); void delete(long id); } // Interface – nur was getan wird, nicht wie. // Geschäftslogik kennt nur diesen Vertrag.
4) Repository vs. DAO – nicht ganz dasselbe
In der Java-Welt gibt es zwei sehr ähnliche Begriffe: DAO (Data Access Object) und Repository. Beide kapseln Datenbankzugriff, aber es gibt einen feinen Unterschied:
| DAO | Repository |
|---|---|
| Näher an der Datenbank, oft pro Tabelle | Näher an der Geschäftslogik, oft pro Aggregat |
Operationen heißen technisch: insert, update, selectById | Operationen klingen wie eine Sammlung: findById, save, add, remove |
| „Speichere diesen Datensatz" | „Hol mir das Kunde-Objekt mit ID 42" |
| Begriff aus der Java-EE-Welt | Begriff aus Domain-Driven Design |
In der Praxis werden die Begriffe oft synonym verwendet, und Spring Data nennt sein Konzept einfach „Repository", auch wenn es technisch näher an einem DAO ist. Für die IHK-Prüfung: beide Begriffe akzeptieren, beim Vergleich aber die Nuance kennen.
5) Wo Repository in deiner Architektur sitzt
Repository ist eine Schicht in einer typischen Layered Architecture. Die übliche Reihenfolge von oben nach unten:
- Controller / API – nimmt HTTP-Anfragen entgegen (siehe REST und MVC).
- Service / Anwendungslogik – orchestriert die Geschäftsregeln.
- Repository – kapselt den Datenzugriff. Hier sitzen wir.
- Datenquelle – DB, externe API, Datei, Cache.
Wichtig: das Repository gehört nicht ins Model, sondern ist eine eigene Schicht. Das Model (z. B. die Klasse Kunde) sollte nichts davon wissen, wie es gespeichert wird – das ist die Aufgabe des Repositories. So bleibt das Model frei von Persistenz-Logik, was Tests und Refactoring erleichtert. Mehr zu Schichten-Architektur in Anforderungen erheben.
6) Spring Data und JPA – Repository „kostenlos"
In modernen Java-Projekten schreibst du Repositories oft gar nicht selbst. Spring Data JPA generiert dir die Implementierung anhand des Interfaces:
@Repository public interface KundeRepository extends JpaRepository<Kunde, Long> { // Spring versteht den Methodennamen // und baut die SQL-Query selbst! List<Kunde> findByOrtAndAktivTrue(String ort); Optional<Kunde> findByEmail(String email); long countByLandIstDeutschland(); }
Du schreibst kein SQL, keine Implementierung – Spring generiert sie automatisch aus den Methodennamen. findByOrtAndAktivTrue wird zu SELECT * FROM kunden WHERE ort = ? AND aktiv = true. Magie, aber genau auf dem Repository-Pattern aufgebaut. Auch andere Frameworks haben Ähnliches: Doctrine in PHP, Entity Framework in C#, Django ORM in Python.
7) Vorteile auf einen Blick
- Austauschbarkeit: Datenbank wechseln, ohne Geschäftslogik zu berühren.
- Testbarkeit: Fake-Repository in Tests einsetzen – kein H2, kein TestContainer nötig für einfache Logik-Tests.
- Trennung der Belange (SoC): SQL gehört nicht in den Service.
- Caching transparent: ein Caching-Repository kann ein anderes Repository umschließen – siehe Decorator und Connection Pooling.
- Wiederverwendbarkeit: dasselbe Repository nutzen Web-Controller und Hintergrund-Jobs.
Stolperfalle: nicht jedes kleine Skript braucht ein Repository. Wenn du ein 50-Zeilen-Skript schreibst, das einmal eine CSV einliest, ist Direct-DB-Zugriff völlig in Ordnung. Repository lohnt sich, sobald die Anwendung wächst, mehrere Datenquellen denkbar werden oder Unit-Tests verlangt sind.
Zusammenfassung
Repository ist eine Schicht, die den Datenzugriff vor der Geschäftslogik verbirgt. Die Logik arbeitet mit Domain-Objekten und ruft Methoden wie findById oder save auf – wo die Daten herkommen (SQL, REST, Datei, Cache), ist ihr egal. Vorteile: austauschbare Datenquelle, viel bessere Testbarkeit, saubere Trennung der Schichten. Repository ähnelt dem älteren DAO, ist aber näher an der Domäne formuliert. In Spring Data JPA wird die Implementierung automatisch aus dem Interface generiert – du schreibst nur Methodennamen wie findByEmail. Sitzt in der Schichtarchitektur zwischen Service und Datenquelle, oft in Verbindung mit Dependency Injection und MVC.
Verwandte Lektionen: MVC · Dependency Injection · Unit-Tests aufbauen · und mehrWeitere relevante LektionenDecoratorFactorySOLID-PrinzipienWas ist eine Datenbank?REST-GrundprinzipienConnection PoolingTrigger & Prozeduren
