Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
| Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
| modul:m290_guko:learningunits:lu17:theorie:a_intro [2026/01/02 22:30] – gkoch | modul:m290_guko:learningunits:lu17:theorie:a_intro [2026/01/12 07:43] (aktuell) – gkoch | ||
|---|---|---|---|
| Zeile 3: | Zeile 3: | ||
| ===== Lernziele ===== | ===== Lernziele ===== | ||
| * Sie können Ihre **MySQL-Datenbank** aus einem Express-Server heraus ansprechen. | * Sie können Ihre **MySQL-Datenbank** aus einem Express-Server heraus ansprechen. | ||
| - | * Sie können die CRUD-Routen aus LU16 ('' | + | * Sie können die CRUD-Routen aus LU16 ('' |
| * Sie setzen einfache **Validierung** ein (Pflichtfelder prüfen). | * Sie setzen einfache **Validierung** ein (Pflichtfelder prüfen). | ||
| * Sie verwenden passende **HTTP-Statuscodes** (200, 201, 400, 404, 500). | * Sie verwenden passende **HTTP-Statuscodes** (200, 201, 400, 404, 500). | ||
| Zeile 19: | Zeile 19: | ||
| In LU17 ersetzen Sie diese In-Memory-Liste durch eine echte Datenbank: | In LU17 ersetzen Sie diese In-Memory-Liste durch eine echte Datenbank: | ||
| - | * Die Daten kommen aus der **MySQL-Tabelle '' | + | * Die Daten kommen aus der **MySQL-Tabelle '' |
| * Ihr Express-Server ist die **Brücke** zwischen Client (Postman) und Datenbank. | * Ihr Express-Server ist die **Brücke** zwischen Client (Postman) und Datenbank. | ||
| * Die gleiche Idee bleibt: **HTTP-Anfrage → Route → Logik/SQL → HTTP-Antwort**. | * Die gleiche Idee bleibt: **HTTP-Anfrage → Route → Logik/SQL → HTTP-Antwort**. | ||
| Zeile 216: | Zeile 216: | ||
| </ | </ | ||
| - | **Test in Postman** | + | === Test in Postman |
| * Methode: '' | * Methode: '' | ||
| * URL: '' | * URL: '' | ||
| Zeile 307: | Zeile 307: | ||
| const newPost = { | const newPost = { | ||
| id: result.insertId, | id: result.insertId, | ||
| - | user_id, | + | |
| - | title, | + | |
| image_url: image_url || '', | image_url: image_url || '', | ||
| description: | description: | ||
| Zeile 319: | Zeile 319: | ||
| </ | </ | ||
| </ | </ | ||
| + | |||
| + | === Test in Postman === | ||
| **Test-Body (Postman → Body → raw → JSON)** | **Test-Body (Postman → Body → raw → JSON)** | ||
| Zeile 335: | Zeile 337: | ||
| ==== UPDATE: Post ändern (PUT / | ==== UPDATE: Post ändern (PUT / | ||
| - | In LU16b haben Sie einen Post so aktualisiert: | + | In LU16b haben Sie einen Post so aktualisiert: |
| Genau diese Logik übernehmen wir jetzt – der Unterschied ist nur: statt im Array ändern wir jetzt die MySQL-Tabelle '' | Genau diese Logik übernehmen wir jetzt – der Unterschied ist nur: statt im Array ändern wir jetzt die MySQL-Tabelle '' | ||
| Zeile 341: | Zeile 343: | ||
| <WRAP box round center 80%> | <WRAP box round center 80%> | ||
| <code javascript> | <code javascript> | ||
| - | // UPDATE – vorhandenen | + | // UPDATE – Post vollständig ersetzen |
| // Route: PUT http:// | // Route: PUT http:// | ||
| - | |||
| app.put('/ | app.put('/ | ||
| - | // 1) ID aus der URL lesen (Route-Parameter) | + | |
| - | const id = Number(req.params.id); | + | |
| - | // ID prüfen: muss eine Zahl sein | + | |
| - | if (Number.isNaN(id)) { | + | return res.status(400).send(' |
| - | return res.status(400).send(' | + | } |
| - | } | + | |
| - | // 2) Mögliche neue Werte aus dem Request-Body lesen | + | |
| - | // (Postman: Body -> raw -> JSON) | + | const user_id = req.body.user_id; |
| - | const user_id = req.body.user_id; | + | const title = req.body.title; |
| - | const title = req.body.title; | + | const image_url = req.body.image_url; |
| - | const image_url = req.body.image_url; | + | const description = req.body.description; |
| - | const description = req.body.description; | + | const likes = req.body.likes; |
| - | const likes = req.body.likes; | + | |
| - | // 3) Validierung: | + | |
| - | // Wichtig: | + | // likes kann 0 sein -> deshalb auf undefined |
| - | if ( | + | if ( |
| - | user_id === undefined | + | user_id === undefined |
| - | title === undefined | + | title === undefined |
| - | image_url === undefined | + | image_url === undefined |
| - | description === undefined | + | description === undefined |
| - | likes === undefined | + | likes === undefined |
| - | ) { | + | ) { |
| - | return res.status(400).send(' | + | return res.status(400).send(' |
| - | } | + | } |
| - | // 4) SQL-UPDATE | + | const sql = ` |
| - | // Nur Felder, die wirklich im Body vorhanden sind, kommen in das SET. | + | |
| - | const setParts | + | SET user_id = ?, title = ?, image_url |
| - | const values | + | WHERE id = ? |
| + | `; | ||
| - | if (user_id !== undefined) { | + | const values |
| - | setParts.push(' | + | |
| - | values.push(user_id); | + | |
| - | } | + | |
| - | if (title !== undefined) { | + | |
| - | setParts.push(' | + | |
| - | values.push(title); | + | |
| - | } | + | |
| - | if (image_url | + | |
| - | setParts.push(' | + | |
| - | values.push(image_url); | + | |
| - | } | + | |
| - | if (description | + | |
| - | setParts.push(' | + | |
| - | values.push(description); | + | |
| - | } | + | |
| - | if (likes !== undefined) { | + | |
| - | setParts.push(' | + | |
| - | values.push(likes); | + | |
| - | } | + | |
| - | // id gehört ans Ende -> wird im WHERE eingesetzt | + | db.query(sql, |
| - | values.push(id); | + | if (err) { |
| + | console.error(' | ||
| + | | ||
| + | } | ||
| - | const sql = UPDATE posts SET ${setParts.join(', ')} WHERE id = ? ; | + | if (result.affectedRows |
| + | return res.status(404).send('Post nicht gefunden'); | ||
| + | } | ||
| - | // 5) UPDATE ausführen | + | |
| - | db.query(sql, | + | res.status(200).json({ |
| - | + | id: id, | |
| - | // DB-Fehler -> 500 | + | user_id: |
| - | if (err) { | + | title: |
| - | console.error(' | + | image_url: |
| - | return | + | description: |
| - | } | + | |
| - | + | | |
| - | // affectedRows = 0 -> es gab keinen Post mit dieser ID | + | }); |
| - | if (result.affectedRows === 0) { | + | |
| - | | + | |
| - | } | + | |
| - | + | ||
| - | // 6) Lernfreundlich: aktualisierten Datensatz nochmals holen und zurückgeben | + | |
| - | // Damit der Client (Postman) das " | + | |
| - | const selectSql = ` | + | |
| - | SELECT | + | |
| - | FROM posts | + | |
| - | WHERE id = ? | + | |
| - | `; | + | |
| - | + | ||
| - | db.query(selectSql, | + | |
| - | if (err2) { | + | |
| - | console.error(' | + | |
| - | | + | |
| - | | + | |
| - | + | ||
| - | res.status(200).json(rows[0]); | + | |
| - | }); | + | |
| - | + | ||
| - | + | ||
| - | }); | + | |
| }); | }); | ||
| </ | </ | ||
| </ | </ | ||
| - | Test mit Postman | + | === Test in Postman |
| - | + | ||
| - | Methode: '' | + | |
| - | + | ||
| - | URL: '' | + | |
| - | '' | + | |
| - | + | ||
| - | Body → '' | + | |
| - | + | ||
| - | Beispiel-Body: | + | |
| + | **Test-Body** | ||
| <WRAP box round center 80%> | <WRAP box round center 80%> | ||
| <code json> | <code json> | ||
| { | { | ||
| - | " | + | " |
| - | " | + | |
| + | " | ||
| + | " | ||
| + | | ||
| } | } | ||
| </ | </ | ||
| Zeile 463: | Zeile 420: | ||
| Erwartung: | Erwartung: | ||
| + | * Status '' | ||
| + | * JSON-Objekt des aktualisierten Posts (inkl. neuem '' | ||
| - | Status '' | ||
| - | |||
| - | JSON-Objekt des aktualisierten Posts (inkl. neuem '' | ||
| - | |||
| - | DELETE-Section ersetzen durch diese Version | ||
| ==== DELETE: Post löschen (DELETE / | ==== DELETE: Post löschen (DELETE / | ||
| - | |||
| - | In LU16b haben Sie beim Löschen den gelöschten Post zurückgegeben (zur Kontrolle). | ||
| - | Das machen wir hier genauso – nur mit MySQL: | ||
| - | |||
| - | zuerst den Post mit '' | ||
| - | |||
| - | dann mit '' | ||
| - | |||
| - | dann den vorher geholten Post zurückgeben. | ||
| - | |||
| <WRAP box round center 80%> | <WRAP box round center 80%> | ||
| <code javascript> | <code javascript> | ||
| - | // DELETE – Post löschen | + | // DELETE – Post löschen |
| - | // Route: DELETE http:// | + | |
| app.delete('/ | app.delete('/ | ||
| - | const id = Number(req.params.id); | + | |
| - | if (Number.isNaN(id)) { | + | |
| - | return res.status(400).send(' | + | return res.status(400).send(' |
| - | } | + | } |
| - | // 1) Post zuerst holen (damit wir ihn nach dem Löschen zurückgeben können) | + | |
| - | const selectSql | + | |
| - | db.query(selectSql, [id], (err, rows) => { | + | |
| + | if (err) { | ||
| + | console.error(' | ||
| + | return res.status(500).send(' | ||
| + | } | ||
| - | if (err) { | + | |
| - | | + | return res.status(404).send(' |
| - | | + | } |
| - | } | + | |
| - | if (rows.length === 0) { | + | // Antwort: 200 + Message |
| - | | + | res.status(200).json({ message: `Post mit id=${id} wurde gelöscht.` }); |
| - | } | + | |
| - | + | ||
| - | const deletedPost = rows[0]; | + | |
| - | + | ||
| - | // 2) Jetzt löschen | + | |
| - | const deleteSql = ' | + | |
| - | + | ||
| - | db.query(deleteSql, | + | |
| - | + | ||
| - | if (err2) { | + | |
| - | console.error(' | + | |
| - | return res.status(500).send(' | + | |
| - | | + | |
| - | + | ||
| - | // 3) Lernfreundlich: | + | |
| - | res.status(200).json(deletedPost); | + | |
| - | }); | + | |
| - | + | ||
| - | + | ||
| - | }); | + | |
| }); | }); | ||
| </ | </ | ||
| </ | </ | ||
| - | Test mit Postman | + | === Test mit Postman |
| - | Methode: '' | + | * Methode: '' |
| - | + | | |
| - | URL: '' | + | |
| - | '' | + | |
| Erwartung: | Erwartung: | ||
| - | + | * Status '' | |
| - | Status '' | + | |
| - | + | | |
| - | JSON-Objekt des gelöschten Posts | + | |
| - | + | ||
| - | Danach '' | + | |
| Zeile 558: | Zeile 478: | ||
| ===== Transfer auf Ihr Projekt (LB03) ===== | ===== Transfer auf Ihr Projekt (LB03) ===== | ||
| - | Für Ihr Projekt ersetzen Sie '' | + | Für Ihr Projekt ersetzen Sie '' |
| * Ressourcen-Route: | * Ressourcen-Route: | ||