Skip to content

Commit abee012

Browse files
committed
chore: initial commit
0 parents  commit abee012

37 files changed

Lines changed: 5725 additions & 0 deletions

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
_build
2+
slide-output
3+
node_modules
4+
slides/_build
5+
docs/_build
6+
.venv
7+
uv.lock

LICENSE

Lines changed: 427 additions & 0 deletions
Large diffs are not rendered by default.

README.md

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
# Database Development
2+
3+
Dieses Repository enthält die Materialien für **Database Development**, das Folgemodul zu **Relational Databases** an der HFTM.
4+
5+
## Ziel des Kurses
6+
7+
Der Kurs zeigt, wie relationale Datenbanken in professioneller Softwareentwicklung eingesetzt werden. Im Zentrum steht die Frage:
8+
9+
> Wie entwickle ich mit PostgreSQL, Spring Boot, Hibernate/JPA und Flyway eine robuste, wartbare und performante datenbankgestützte Anwendung?
10+
11+
Die konkrete Unterrichtstechnologie ist Spring Boot. Die behandelten Prinzipien bleiben aber bewusst übertragbar: Datenmodellierung, ORM, Migrationen, Transaktionen, Query Design, Performance und Tests.
12+
13+
## Leitfallstudie
14+
15+
Alle Materialien arbeiten mit einem **Ticket-System für internen Support**. Die Fallstudie ist klein genug für Unterrichtslektionen und reich genug für typische Datenbankentwicklungsfragen:
16+
17+
- Benutzer, Teams und Zuständigkeiten
18+
- Tickets mit Status, Priorität und Verantwortlichen
19+
- Kommentare und Ereignisverlauf
20+
- Labels und n:m-Beziehungen
21+
- Reporting-Abfragen, Transaktionen, Migrationen und Performance-Fragen
22+
23+
## Struktur
24+
25+
- `docs/` - Lehrbuch im MyST/Jupyter-Book-Format
26+
- `slides/` - Marp-Folien mit HFTM-Theme
27+
- `planning/` - Unterrichtsplanung
28+
- `exercises/` - Diagnose- und Übungsaufgaben
29+
- `postgres/` - PostgreSQL-Container, Schema und Testdaten
30+
31+
## Voraussetzungen
32+
33+
- Python 3.12+
34+
- Poetry
35+
- Node.js 18+
36+
- Docker oder Podman
37+
38+
## Lehrbuch bauen
39+
40+
```bash
41+
poetry install
42+
cd docs
43+
jupyter book build --site
44+
```
45+
46+
Mit aktivierter Poetry-Umgebung kannst du alternativ aus dem Projektroot bauen:
47+
48+
```bash
49+
npm run docs:build
50+
```
51+
52+
Hinweis: `jupyter book build .` funktioniert mit dem MyST-basierten Jupyter-Book-CLI nicht, weil `.` als Dateiargument interpretiert wird.
53+
54+
## Folien starten
55+
56+
```bash
57+
npm install
58+
npm run slides:serve
59+
```
60+
61+
Die Folien werden standardmässig auf Port `5002` bereitgestellt.
62+
63+
## PostgreSQL-Fallstudie starten
64+
65+
```bash
66+
cd postgres
67+
docker compose up --build
68+
```
69+
70+
Verbindungsdaten:
71+
72+
- Host: `localhost`
73+
- Port: `5433`
74+
- Datenbank: `ticket_system`
75+
- Benutzer: `ticket_user`
76+
- Passwort: `ticket_user`
77+
78+
## Lizenz
79+
80+
Dieses Werk steht unter der Creative Commons Attribution-ShareAlike 4.0 International License (CC-BY-SA 4.0).

citation_guide.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# Zitierleitfaden
2+
3+
Quellen werden im Lehrbuch mit MyST-Zitationen direkt im Text referenziert:
4+
5+
```markdown
6+
{cite}`citation_key`
7+
```
8+
9+
Die zugehörigen BibTeX-Einträge liegen in `docs/references.bib`.
10+
11+
Für selbst erstellte Aufgaben, grundlegende SQL-Syntax und eigene Unterrichtsbeispiele ist keine Zitation nötig. Extern belegte technische Aussagen, historische Einordnungen oder konkrete Aussagen zu Frameworks erhalten eine Quelle.

docs/0_intro.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# Database Development
2+
3+
Willkommen zu **Database Development**, dem Folgemodul zu **Relational Databases**.
4+
5+
In **Relational Databases** hast du relationale Datenbanken aus Sicht von SQL, Modellierung, Normalisierung, Transaktionen und ersten ORM-Konzepten kennengelernt. In **Database Development** verschiebt sich die Perspektive: Die Datenbank ist nicht mehr nur ein System, das du bedienst. Sie wird Teil einer Softwarearchitektur.
6+
7+
Die zentrale Frage lautet:
8+
9+
> Wie entwickelst du mit PostgreSQL, Spring Boot, Hibernate/JPA und Flyway eine robuste, wartbare und performante datenbankgestützte Anwendung?
10+
11+
Spring Boot ist in diesem Kurs die konkrete Lernumgebung {cite}`spring_boot_reference`. Für den Datenbankzugriff arbeiten wir mit Spring Data JPA und Hibernate/JPA {cite}`spring_data_jpa_reference` {cite}`hibernate_orm_user_guide`. Schemaänderungen werden mit Flyway als versionierte Migrationen gedacht {cite}`flyway_documentation`. PostgreSQL bleibt unser relationales Referenzsystem {cite}`postgresql_documentation`.
12+
13+
:::{important} Lernziele des Moduls
14+
Nach Abschluss des Moduls kannst du:
15+
16+
- ein kleines Spring-Boot-Backend mit PostgreSQL fachlich sinnvoll strukturieren.
17+
- Datenmodelle mit JPA Entities, Beziehungen, Constraints und DTO-Abgrenzung abbilden.
18+
- Flyway-Migrationen planen, schreiben und Risiken von Schemaänderungen einschätzen.
19+
- Transaktionsgrenzen im Anwendungscode mit `@Transactional` begründen.
20+
- Repository Methods, JPQL und native SQL Queries situationsgerecht einsetzen.
21+
- typische ORM-Probleme wie N+1, falsches Lazy Loading und ungeeignete Abfragen erkennen.
22+
- Query-Performance mit `EXPLAIN`, einfachen Indexüberlegungen und API-Zugriffsmustern beurteilen.
23+
- Integrationstests gegen echte PostgreSQL-Instanzen konzeptionell einordnen, etwa mit Testcontainers {cite}`testcontainers_documentation`.
24+
:::
25+
26+
## Die Leitfallstudie
27+
28+
Wir arbeiten durchgehend mit einem **Ticket-System für internen Support**. Dieses System ist absichtlich nah an typischen Entwicklungsprojekten:
29+
30+
- Mitarbeitende erstellen Tickets.
31+
- Support-Teams übernehmen Zuständigkeiten.
32+
- Tickets haben Status, Priorität, Kommentare und Ereignisse.
33+
- Labels erlauben flexible Kategorisierung.
34+
- Reporting-Abfragen zeigen Trends und Engpässe.
35+
36+
Diese Fallstudie ist klein genug, damit du sie im Unterricht überblicken kannst. Gleichzeitig enthält sie genug Reibung für echte Datenbankentwicklungsfragen: Transaktionsgrenzen, n:m-Beziehungen, Migrationen, ORM-Ladestrategien, Reporting Queries und Performance.
37+
38+
## Aufbau des Moduls
39+
40+
Das Modul umfasst neun Blöcke zu je drei Lektionen:
41+
42+
| Block | Thema | Schwerpunkt |
43+
| --- | --- | --- |
44+
| 1 | Wiederholung und Standortbestimmung | Relevantes Vorwissen aus **Relational Databases** aktivieren |
45+
| 2 | Spring Boot, PostgreSQL und Datenbankzugriff | Projektstruktur, Konfiguration, Repository- und Service-Layer |
46+
| 3 | Hibernate/JPA Grundlagen | Entities, Beziehungen, Repositories, CRUD |
47+
| 4 | Transaktionen und Datenkonsistenz | `@Transactional`, Rollback, Invarianten |
48+
| 5 | Schema Design für Softwareprojekte | Constraints, IDs, Statusmodellierung, DTO-Abgrenzung |
49+
| 6 | Flyway und Schema Evolution | Migrationen, Datenmigrationen, sichere Änderungsschritte |
50+
| 7 | Query Design | Repository Methods, JPQL, native SQL und Reporting |
51+
| 8 | Performance und ORM-Probleme | N+1, Lazy/Eager Loading, Pagination, `EXPLAIN`, Indexe |
52+
| 9 | Projektarbeit und Prüfungsvorbereitung | Review, Konsolidierung, Prüfungstraining |
53+
54+
## Arbeitsweise
55+
56+
Du wirst in diesem Modul viel lesen, vergleichen und begründen. Das ist Absicht. Datenbankentwicklung besteht nicht nur darin, Code zum Laufen zu bringen. Gute Entwicklerinnen und Entwickler können erklären, warum eine Beziehung so modelliert ist, warum eine Query so geschrieben wurde, wo eine Transaktion beginnt und weshalb eine Migration sicher oder riskant ist.
57+
58+
Die Blöcke folgen deshalb einem wiederkehrenden Muster:
59+
60+
1. Ein realistisches Problem aus der Softwareentwicklung.
61+
2. Eine kompakte fachliche Einordnung.
62+
3. Eine angeleitete Umsetzung oder Analyse.
63+
4. Eine Transferfrage für ähnliche Situationen.
64+
65+
Im ersten Block beginnen wir mit einer Standortbestimmung. Sie zeigt, welche Grundlagen aus **Relational Databases** du bereits sicher einsetzen kannst und welche Themen in **Database Development** bewusst vertieft werden.
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Wiederholung und Standortbestimmung
2+
3+
Der erste Block verbindet **Relational Databases** mit **Database Development**. Du wiederholst nicht die ganze Welt relationaler Datenbanken. Stattdessen aktivierst du genau jene Grundlagen, die in einer datenbankgestützten Anwendung sofort wichtig werden:
4+
5+
- SQL-Abfragen lesen und korrigieren
6+
- Beziehungen und Constraints verstehen
7+
- Transaktionen fachlich begründen
8+
- ORM und direktes SQL einordnen
9+
- Schemaänderungen als Teil von Softwareentwicklung sehen
10+
11+
Die Leitfallstudie ist ein internes Ticket-System. Es ist bewusst einfach genug für eine Standortbestimmung, aber realistisch genug für spätere Blöcke zu Spring Boot, JPA, Flyway und Performance.
12+
13+
:::{important} Lernziele
14+
Nach diesem Block kannst du:
15+
16+
- das Ticket-Schema fachlich erklären.
17+
- typische SQL-Abfragen mit Joins und Aggregationen nachvollziehen.
18+
- wichtige Constraints und Beziehungstypen begründen.
19+
- eine einfache Transaktionsgrenze für einen kritischen Vorgang skizzieren.
20+
- erklären, weshalb Wissen aus **Relational Databases** in Anwendungscode sichtbar bleibt.
21+
:::
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Was aus Relational Databases jetzt zählt
2+
3+
In **Relational Databases** hast du viele Grundlagen kennengelernt. Für **Database Development** sind nicht alle gleich wichtig. Entscheidend ist, ob du sie in einer Anwendungssituation wiedererkennst.
4+
5+
Stell dir vor, ein API-Endpunkt soll alle offenen Tickets eines Teams anzeigen. Schon diese scheinbar einfache Anforderung berührt mehrere Themen aus **Relational Databases**:
6+
7+
- Welche Tabellen sind beteiligt?
8+
- Welche Beziehung ist verpflichtend, welche optional?
9+
- Braucht es `JOIN` oder `LEFT JOIN`?
10+
- Welche Spalten werden gefiltert?
11+
- Welche Constraints schützen die Daten, falls der Anwendungscode fehlerhaft ist?
12+
- Kann das ORM die Abfrage sinnvoll erzeugen oder braucht es gezieltes SQL?
13+
14+
## SQL als gemeinsame Sprache
15+
16+
Auch wenn spätere Blöcke mit Spring Data JPA und Hibernate arbeiten, bleibt SQL die gemeinsame Sprache zwischen Anwendung und Datenbank. Ein Repository kann dir Schreibarbeit abnehmen. Es nimmt dir aber nicht die Verantwortung ab, Datenzugriffe zu verstehen.
17+
18+
Besonders wichtig bleiben:
19+
20+
- `SELECT`, `WHERE`, `ORDER BY`
21+
- `JOIN`, `LEFT JOIN`
22+
- `GROUP BY`, Aggregatfunktionen und `HAVING`
23+
- Primärschlüssel, Fremdschlüssel und eindeutige Werte
24+
- Transaktionen mit Commit und Rollback
25+
26+
## Modellierung als Architekturentscheidung
27+
28+
Eine Datenbankstruktur ist nicht nur eine technische Ablageform. Sie prägt, wie Anwendungscode aussieht. Eine falsch modellierte n:m-Beziehung führt später zu umständlichen Queries, komplizierten DTOs oder fehleranfälliger Geschäftslogik.
29+
30+
Im Ticket-System ist die Beziehung zwischen Tickets und Labels ein gutes Beispiel. Ein Ticket kann mehrere Labels haben, und ein Label kann zu vielen Tickets gehören. Deshalb braucht es eine Zwischentabelle `ticket_labels`. Ein Textfeld mit kommagetrennten Labels wäre schneller hingeschrieben, aber schlechter abfragbar, schwerer validierbar und weniger robust.
31+
32+
## Transaktionen als Schutz fachlicher Abläufe
33+
34+
Transaktionen werden in **Database Development** aus Anwendungssicht betrachtet. Du fragst nicht nur: "Was ist ACID?", sondern:
35+
36+
> Welche Schritte müssen gemeinsam erfolgreich sein, damit der fachliche Zustand korrekt bleibt?
37+
38+
Beim Erstellen eines Tickets gehören beispielsweise Ticket, erster Kommentar und Ereigniseintrag zusammen. Wenn der Kommentar fehlschlägt, soll nicht trotzdem ein halbfertiges Ticket übrig bleiben.
39+
40+
Genau hier wird später `@Transactional` im Service-Layer wichtig.
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
# Die Ticket-Fallstudie
2+
3+
Das Ticket-System bildet interne Supportprozesse ab. Es enthält Mitarbeitende, Support-Teams, Tickets, Kommentare, Ereignisse und Labels.
4+
5+
```mermaid
6+
erDiagram
7+
TEAMS ||--o{ USERS : has
8+
TEAMS ||--o{ TICKETS : owns
9+
USERS ||--o{ TICKETS : creates
10+
USERS ||--o{ TICKETS : handles
11+
TICKETS ||--o{ TICKET_COMMENTS : contains
12+
USERS ||--o{ TICKET_COMMENTS : writes
13+
TICKETS ||--o{ TICKET_EVENTS : records
14+
USERS ||--o{ TICKET_EVENTS : triggers
15+
TICKETS ||--o{ TICKET_LABELS : has
16+
LABELS ||--o{ TICKET_LABELS : classifies
17+
```
18+
19+
## Zentrale Tabellen
20+
21+
| Tabelle | Zweck |
22+
| --- | --- |
23+
| `users` | Personen, die Tickets erstellen oder bearbeiten |
24+
| `teams` | Zuständigkeiten und organisatorische Gruppen |
25+
| `tickets` | eigentliche Support-Fälle |
26+
| `ticket_comments` | Kommunikation und interne Notizen |
27+
| `ticket_events` | nachvollziehbarer Verlauf wichtiger Änderungen |
28+
| `labels` | wiederverwendbare Kategorien |
29+
| `ticket_labels` | n:m-Zuordnung zwischen Tickets und Labels |
30+
31+
## Warum diese Fallstudie passt
32+
33+
Das Ticket-System ist für Softwareentwickler intuitiv. Gleichzeitig entstehen echte Datenbankfragen:
34+
35+
- Ein Ticket muss genau ein erstellendes Benutzerkonto haben.
36+
- Ein Ticket kann noch keiner verantwortlichen Person zugewiesen sein.
37+
- Ein Ticket kann mehrere Labels erhalten.
38+
- Status und Priorität sollen kontrollierte Werte haben.
39+
- Kommentar und Event müssen oft in derselben Transaktion gespeichert werden.
40+
- Reporting braucht Joins und Aggregationen.
41+
42+
## Beispielabfrage
43+
44+
Die folgende Query zeigt offene Tickets mit Team und verantwortlicher Person. Weil ein Ticket noch nicht zugewiesen sein muss, wird für die verantwortliche Person ein `LEFT JOIN` verwendet.
45+
46+
```sql
47+
SELECT
48+
t.id,
49+
t.title,
50+
t.status,
51+
t.priority,
52+
team.name AS team_name,
53+
assignee.display_name AS assigned_to
54+
FROM tickets t
55+
JOIN teams team ON team.id = t.team_id
56+
LEFT JOIN users assignee ON assignee.id = t.assigned_to_id
57+
WHERE t.status NOT IN ('resolved', 'closed')
58+
ORDER BY t.priority DESC, t.created_at;
59+
```
60+
61+
Diese Query ist klein, aber sie zeigt bereits die Richtung des Kurses: Datenbankmodell, fachliche Bedeutung und späterer API-Zugriff gehören zusammen.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# Diagnoseaufgabe
2+
3+
Die Standortbestimmung ist eine Lernaufgabe, keine Falle. Sie zeigt, welche Grundlagen du sicher abrufen kannst und wo du in den nächsten Blöcken aufmerksam sein solltest.
4+
5+
## Teil 1: Schema lesen
6+
7+
Erkläre mit eigenen Worten:
8+
9+
- Warum `tickets.team_id` verpflichtend ist.
10+
- Warum `tickets.assigned_to_id` optional ist.
11+
- Warum `ticket_labels` einen zusammengesetzten Primärschlüssel hat.
12+
- Welche Daten beim Anzeigen einer Ticket-Liste wahrscheinlich gebraucht werden.
13+
14+
## Teil 2: SQL korrigieren
15+
16+
Eine fehlerhafte Query ist ein realistisches Arbeitsmittel. In Projekten liest du oft bestehenden Code und musst entscheiden, ob er fachlich korrekt ist.
17+
18+
Typische Fragen:
19+
20+
- Fehlt eine Join-Bedingung?
21+
- Werden optionale Beziehungen versehentlich ausgeschlossen?
22+
- Wird vor oder nach der Gruppierung gefiltert?
23+
- Ist die Query für den späteren API-Fall verständlich?
24+
25+
## Teil 3: Transaktion skizzieren
26+
27+
Beim Erstellen eines Tickets sollen drei Operationen zusammengehören:
28+
29+
1. Ticket speichern
30+
2. ersten Kommentar speichern
31+
3. Event `created` speichern
32+
33+
Wenn Schritt 2 fehlschlägt, muss Schritt 1 zurückgerollt werden. Sonst entsteht ein Ticket ohne Startkommunikation und ohne vollständigen Verlauf. Das ist kein SQL-Detail, sondern eine fachliche Konsistenzregel.
34+
35+
## Teil 4: Zugriffstechnik einordnen
36+
37+
Nicht jeder Datenzugriff braucht dieselbe Technik:
38+
39+
| Situation | Häufig passende Technik |
40+
| --- | --- |
41+
| Ein Ticket per ID laden | Repository Method |
42+
| Offene Tickets eines Teams laden | Repository Method oder JPQL |
43+
| Reporting über Teams, Status und Priorität | native SQL oder gezielte Projektion |
44+
| Tickets mit Kommentaren ohne N+1 laden | JPQL mit Fetch-Strategie oder DTO-Projektion |
45+
46+
Die genaue Entscheidung hängt vom Projekt ab. Wichtig ist, dass du sie begründen kannst.
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Brücke zu Spring Boot, JPA und Flyway
2+
3+
Block 1 endet dort, wo **Database Development** richtig beginnt: bei der Frage, wie Datenbankentscheidungen im Anwendungscode sichtbar werden.
4+
5+
## Vom SQL-Schema zur Anwendung
6+
7+
In einer Spring-Boot-Anwendung treffen mehrere Schichten aufeinander:
8+
9+
```mermaid
10+
flowchart LR
11+
A[HTTP Request] --> B[Controller]
12+
B --> C[Service]
13+
C --> D[Repository]
14+
D --> E[(PostgreSQL)]
15+
```
16+
17+
Der Controller nimmt Anfragen entgegen. Der Service enthält fachliche Abläufe und Transaktionsgrenzen. Das Repository kapselt den Datenzugriff. PostgreSQL erzwingt Constraints und speichert den Zustand dauerhaft.
18+
19+
Diese Schichten sind nicht einfach Ordner im Projekt. Sie verteilen Verantwortung.
20+
21+
## ORM hilft, ersetzt aber kein Verständnis
22+
23+
Hibernate/JPA kann Entities auf Tabellen abbilden, Beziehungen laden und SQL generieren. Das ist produktiv und in vielen Anwendungen sinnvoll. Gleichzeitig entstehen typische Fragen:
24+
25+
- Wird eine Beziehung zu früh oder zu spät geladen?
26+
- Entsteht ein N+1-Problem?
27+
- Passt die Entity-Struktur zur API?
28+
- Ist eine Query als Repository Method noch lesbar?
29+
- Braucht ein Reporting-Fall natives SQL?
30+
31+
**Database Development** trainiert genau diese Entscheidungen.
32+
33+
## Migrationen statt zufälliger Schemaänderungen
34+
35+
Im Unterricht wird das Ticket-Schema zuerst als SQL-Schema sichtbar. Später wird es mit Flyway versioniert. Damit wird eine wichtige professionelle Regel eingeführt:
36+
37+
> Das Datenbankschema entwickelt sich kontrolliert mit der Anwendung.
38+
39+
Eine Spalte hinzuzufügen ist einfach. Schwieriger ist die Frage, was mit bestehenden Daten passiert, wann Constraints aktiviert werden und wie ein Team die Änderung nachvollziehen kann.
40+
41+
## Transaktionsgrenzen gehören in den Service
42+
43+
In **Relational Databases** hast du Transaktionen als Datenbankkonzept kennengelernt. In **Database Development** wird daraus eine Architekturentscheidung:
44+
45+
```java
46+
@Transactional
47+
public TicketDto createTicket(CreateTicketRequest request) {
48+
// Ticket speichern
49+
// ersten Kommentar speichern
50+
// Event schreiben
51+
// bei Fehler: Rollback
52+
}
53+
```
54+
55+
Die Annotation ist nur die technische Oberfläche. Entscheidend ist die fachliche Frage: Welche Zustandsänderungen gehören untrennbar zusammen?

0 commit comments

Comments
 (0)