18 VIEWS

Domain Driven Design Repositories mit Spring Data

29.07.2021

Repositories sind einer der Bestandteile im Domain Driven Design. Mit Spring Data lassen sich Repositories für den Datenbankzugriff einfach und ohne Boilerplate-Code umsetzen. Aber wie implementiert man das insbesondere hinsichtlich Trennung des Domain Models von der Infrastruktur?

DDD-Repository mit Spring Data – ein Beispiel

Ein Hinweis noch vorab: Kenntnisse zu Domain Driven Design und Spring Data werden für diesen Artikel vorausgesetzt.

 

Im Domain Driven Design definiert man Repositories für Datenbankzugriffe innerhalb des Domain Models. Und zwar in der Regel anhand von Interfaces, da die Implementierungen abhängig von der Infrastruktur sind (d.h. von der verwendeten Technologie für den Datenbankzugriff), und daher in der Infrastrukturschicht, außerhalb des Domain Models, verortet sein sollten.

 

Schichtenarchitektur
Quelle: Eigene Darstellung

Das Repository-Interface gehört also in den gelben, die Implementierung in den blauen Bereich der im Diagramm dargestellten Schichtenarchitektur. Aber halt – in Spring Data definieren wir ja nur Interfaces. Die Implementierung schreiben wir gar nicht selbst; diese wird von Spring Data automatisch generiert!

Also könnten wir das Spring-Data-Interface ja direkt im Domain Model definieren, oder?

 

 

Das sähe dann so aus (man beachte das domain.model“ im Packagenamen):

Trennung von  Domain Model und Infrastruktur

Mit dem Import des CrudRepository und der Ableitung davon ist allerdings nun ein Detail der Infrastruktur ins Domänenmodell gesickert.

Das wollen wir nicht – also passen wir das Interface an und entfernen die Spring-Data-spezifischen Anteile:

So bringt uns das Interface allerdings nicht mehr viel. Die erste Variante wäre schon nutzbar gewesen, da CrudRepository bereits eine Reihe an Methoden mitbringt. Unser neues Interface leitet allerdings nicht mehr davon ab und besitzt daher auch keine Methoden mehr.

Daher müssen wir die benötigten Methoden nun hier definieren:

Nun definieren wir das Spring-Data-Interface in der Infrastrukturschicht. Gemäß des Ports-And-Adapters-Architekturstils, einer Ausprägung des oben illustrierten Schichtenmodells, kommt das Interface ins Package .port.adapter.persistence“:. Ich nenne das Interface JdbcItemRepository“, weil ich für das Beispiel Spring Data JDBC verwendet habe:

Der Clou an der Sache: das Interface erbt sowohl von unserem ItemRepository aus dem Domain Model, als auch von Spring Datas CrudRepository! So findet Spring Data auch die Methoden, die nur in unserem ItemRepository definiert sind, nicht aber in CrudRepository – wie im obigen Beispiel die Methode findByName(…) – und generiert entsprechende Implementierungen für uns.

Lediglich Methoden mit einer @Query-Annotation müssen in beiden Interfaces definiert werden. Einmal mit den Annotationen, und zwar wegen Bezug zur Infrastruktur in JdbcItemRepository, und dann noch einmal im ItemRepository, damit die Methode darüber aufgerufen werden kann. Dort dann natürlich ohne Annotationen.

In der Projektstruktur sieht das Ganze dann wie folgt aus:

Quelle: Eigene Darstellung

Die Packagestruktur ist übrigens den Beispielen aus dem Buch „Implementing Domain Driven Design“ von Vaughn Vernon nachempfunden.

 

Fazit

Mit Spring Data lassen sich Repositories sehr einfach umsetzen. Und mit einem kleinen Kniff lässt sich auch eine saubere Schichtenarchitektur mit Trennung von Domänen- und Infrastrukturschicht erreichen.

Der Quellcode für das Demoprojekt ist auf GitHub veröffentlicht:
https://github.com/swa-ds/ddd-repo-demo

Zurück zur Übersicht

Kommentar verfassen

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

*Pflichtfelder

*