Dies ist eine alte Version des Dokuments!
LU17 – CRUD mit Express & MySQL (Tabelle ''post'')
Learning Objectives
- Sie können eine MySQL-Datenbank aus Ihrem Express-Server heraus ansprechen.
- Sie können CRUD-Routen für
postsso erweitern, dass sie mit einer echten Tabellepostarbeiten. - Sie setzen einfache Validierung ein (Pflichtfelder prüfen).
- Sie verwenden passende HTTP-Statuscodes (200, 201, 400, 404, 500).
- Sie testen alle Operationen mit Postman.
Ausgangslage
In LU16 haben Sie eine kleine API für Social-Media-Posts gebaut:
- In-Memory-Liste
postsim Code, - Routen wie:
GET /postsGET /posts/:idPOST /posts
Jetzt machen wir einen wichtigen Schritt in Richtung „echte“ Anwendung:
- Die Daten kommen nicht mehr aus einer JS-Liste,
- sondern aus einer MySQL-Tabelle
post, - Ihr Express-Server wird zur Brücke zwischen Client (Postman/Browser) und Datenbank.
Vorbereitung: MySQL-Tabelle ''post''
Eine mögliche Tabellenstruktur (vereinfacht):
| Spalte | Datentyp | Beschreibung |
|---|---|---|
post_id | INT, PK, AI | Primärschlüssel |
user_id | INT | Referenz auf User (FK) |
title | VARCHAR(255) | Titel des Posts |
image_url | VARCHAR(512) | Bild-URL |
description | TEXT | Beschreibungstext |
likes | INT | Anzahl Likes |
Diese Tabelle können Sie wie gewohnt mit einem SQL-DDL-Skript anlegen. (Entweder vorgegeben im Unterricht oder von Ihnen selbst erstellt.)
MySQL aus Node.js ansprechen
Wir verwenden das Paket mysql2 für die Verbindung:
1. Installation von mysql2
Im Projektordner (Terminal in WebStorm):
npm install mysql2
Dadurch wird die Bibliothek in node_modules installiert und in package.json als Abhängigkeit eingetragen.
2. Verbindung zur Datenbank herstellen
Wir erweitern unseren Server aus LU16 um eine Datenbankverbindung.
Alles bleibt weiterhin in einer Datei (z.B. index.js), um es für das Modul einfach zu halten.
import express from 'express'; import mysql from 'mysql2'; const app = express(); const port = 3000; app.use(express.json()); // Verbindung zur MySQL-Datenbank const db = mysql.createConnection({ host: 'localhost', database: 'social_media', // Ihre DB user: 'restrictedUser', // AppUser, nicht root password: 'SafePassword123' }); db.connect((err) => { if (err) { console.error('DB-Verbindung fehlgeschlagen:', err); return; } console.log('Mit MySQL verbunden'); }); // Test-Route app.get('/', (req, res) => { res.send('API mit Datenbank ist online'); }); app.listen(port, () => { console.log(`API läuft auf http://localhost:${port}`); });
Wenn Sie den Server starten (npm run dev) und im Terminal
„Mit MySQL verbunden“ sehen, ist die Verbindung erfolgreich.
READ – Posts aus der Datenbank holen
Jetzt ersetzen wir die In-Memory-Liste durch echte SELECT-Abfragen.
1. Alle Posts – ''GET /posts''
// READ – alle Posts aus der DB app.get('/posts', (req, res) => { const sql = ` SELECT post_id, user_id, title, image_url, description, likes FROM post `; db.query(sql, (err, results) => { if (err) { console.error('DB-Fehler bei GET /posts:', err); return res.status(500).send('Serverfehler bei der Post-Abfrage'); } res.status(200).json(results); }); });
Test mit Postman
- Methode:
GET - Erwartung:
- Status
200 OK - JSON-Array mit allen Zeilen aus der Tabelle
post
2. Einzelner Post – ''GET /posts/:id''
// READ – einzelner Post nach ID aus der DB app.get('/posts/:id', (req, res) => { const id = Number(req.params.id); const sql = ` SELECT post_id, user_id, title, image_url, description, likes FROM post WHERE post_id = ? `; db.query(sql, [id], (err, results) => { if (err) { console.error('DB-Fehler bei GET /posts/:id:', err); return res.status(500).send('Serverfehler bei der Post-Abfrage'); } if (results.length === 0) { return res.status(404).send('Post nicht gefunden'); } res.status(200).json(results[0]); }); });
CREATE – Neuen Post in der DB speichern
Jetzt bauen wir die POST /posts-Route so um, dass sie INSERT in die MySQL-Tabelle ausführt.
// CREATE – neuen Post in der DB anlegen app.post('/posts', (req, res) => { const { user_id, title, image_url, description } = req.body; // Einfache Validierung der Pflichtfelder if (!user_id || !title) { return res.status(400).send('Bitte mindestens user_id und title angeben.'); } const sql = ` INSERT INTO post (user_id, title, image_url, description, likes) VALUES (?, ?, ?, ?, 0) `; const values = [ user_id, title, image_url || '', description || '' ]; db.query(sql, values, (err, result) => { if (err) { console.error('DB-Fehler bei POST /posts:', err); return res.status(500).send('Serverfehler beim Erstellen des Posts'); } // Neu erzeugte ID steht in result.insertId const newPost = { post_id: result.insertId, user_id, title, image_url: image_url || '', description: description || '', likes: 0 }; res.status(201).json(newPost); }); });
Test mit Postman
- Methode:
POST - Body (JSON):
{
"user_id": 1,
"title": "Neuer DB-Post",
"image_url": "https://example.com/post.jpg",
"description": "Dieser Post wurde in MySQL gespeichert."
}
- Erwartung:
- Status
201 Created - JSON-Objekt mit neuer
post_id - Eintrag ist in der Tabelle
postsichtbar
UPDATE – Bestehenden Post ändern (PUT /posts/:id)
Wir implementieren jetzt ein UPDATE mit einfacher Validierung.
// UPDATE – vorhandenen Post aktualisieren app.put('/posts/:id', (req, res) => { const id = Number(req.params.id); const { title, image_url, description, likes } = req.body; // Mindestens ein Feld muss geändert werden if (!title && !image_url && !description && likes === undefined) { return res.status(400).send( 'Bitte mindestens eines der Felder title, image_url, description oder likes angeben.' ); } const sql = ` UPDATE post SET title = COALESCE(?, title), image_url = COALESCE(?, image_url), description = COALESCE(?, description), likes = COALESCE(?, likes) WHERE post_id = ? `; const values = [ title ?? null, image_url ?? null, description ?? null, likes ?? null, id ]; db.query(sql, values, (err, result) => { if (err) { console.error('DB-Fehler bei PUT /posts/:id:', err); return res.status(500).send('Serverfehler beim Aktualisieren des Posts'); } if (result.affectedRows === 0) { return res.status(404).send('Post nicht gefunden'); } res.status(200).send(`Post mit ID ${id} wurde aktualisiert.`); }); });
Hinweise zur Validierung
- Wenn gar keine Felder im Body sind →
400 Bad Request - Wenn die ID in der DB nicht existiert →
404 Not Found - Bei Datenbankfehler →
500 Internal Server Error
DELETE – Post löschen (DELETE /posts/:id)
Zum Schluss implementieren wir DELETE:
// DELETE – Post löschen app.delete('/posts/:id', (req, res) => { const id = Number(req.params.id); const sql = 'DELETE FROM post WHERE post_id = ?'; db.query(sql, [id], (err, result) => { if (err) { console.error('DB-Fehler bei DELETE /posts/:id:', err); return res.status(500).send('Serverfehler beim Löschen des Posts'); } if (result.affectedRows === 0) { return res.status(404).send('Post nicht gefunden'); } res.status(200).send(`Post mit ID ${id} wurde gelöscht.`); }); });
Zusammenfassung & Transfer auf Ihr Projekt
In dieser Learning Unit haben Sie:
- Ihren Express-Server mit MySQL verbunden (
mysql2), - CRUD-Routen für
postsso erweitert, dass sie auf die echte Tabellepostzugreifen, - einfache Validierung eingebaut (Pflichtfelder, leere Updates),
- sinnvolle HTTP-Statuscodes verwendet:
201für erfolgreiches Erstellen,200für erfolgreiche Lese-/Update-/Delete-Operationen,400bei falschen Eingaben,404bei nicht gefundenen Datensätzen,500bei Server-/Datenbankfehlern.
Nächster Schritt für Ihr Modulprojekt:
- Erstellen Sie für Ihren eigenen Use Case (Reisen, Filme, Bücher, …) eine entsprechende Tabelle (oder mehrere Tabellen).
- Bauen Sie ähnliche Routen:
GET /[ressource],GET /[ressource]/:idPOST /[ressource]PUT /[ressource]/:idDELETE /[ressource]/:id
- Testen Sie alles mit Postman.
- Nutzen Sie diese Struktur als Grundlage für die LB3-Projektarbeit.
Vocabulary
| English | Deutsch |
|---|---|
| query | Abfrage (SQL) |
| result set | Resultatmenge (Abfrage-Ergebnis) |
| to insert | einfügen |
| to update | aktualisieren |
| to delete | löschen |
| error handling | Fehlerbehandlung |
| validation | Validierung / Eingabeprüfung |