[[oktatas:web:nodejs:rest_api:sequelize|< Sequelize]] ====== Sequelize kezdés ====== * **Szerző:** Sallai András * Copyright (c) 2022, Sallai András * Szerkesztve: 2022, 2023, 2024 * Licenc: [[https://creativecommons.org/licenses/by-sa/4.0/|CC BY-SA 4.0]] * Web: https://szit.hu ===== Bevezetés ===== A Sequelize egy **ORM**, azaz Object-Relational Mapping, magyarul Objektum-relációs leképző eszköz. Ebben a leírásban **Sequelize**, **Express**, **Sqlite3** és **Nodemon**-t használjuk az alkalmazás létrehozására. A fejlesztés során használjuk a **sequelize-cli** parancsot. Ennek dokumentációja itt található: * https://github.com/sequelize/cli A Sequelize weboldala: * https://sequelize.org/ A Sequelize biztosítja az adatbázis elérést. ===== Projekt létrehozása ===== mkdir app01 cd app01 git init A projekt függőségeinek telepítése: npm init -y npm install sequelize sqlite3 npm install --save-dev sequelize-cli További függőség: npm install express nodemon MariaDB/MySQL esetén: npm install mysql2 Vagy: npm install mariadb ===== A Sequelize-cli beállítása ===== ==== Beállítás nélkül ==== Ha nem készítünk .sequelize fájlt, akkor a következő könyvtárszerkezet jön létre: app01/ |-config/ | `-config.json |-migrations/ |-models/ | `-index.js |-node_modules/ |-seeders/ |-package-lock.json `-package.json ==== app használata ==== Készítsünk a sequelize-cli számára egy beállítást, a **.sequelizerc** fájlban: const path = require('path'); module.exports = { 'models-path': path.resolve('app', 'models'), 'seeders-path': path.resolve('database', 'seeders'), 'migrations-path': path.resolve('database', 'migrations') }; A modelleket az app könyvtáron belül fogjuk elhelyezni, a seeder és migrations eszközöket a database könyvtárban. ==== src használata ==== Az src könyvtárba kerül minden forrásfájl. const path = require('path'); module.exports = { 'config': path.resolve('src', 'config', 'database.json'), 'models-path': path.resolve('src', 'models'), 'seeders-path': path.resolve('src', 'database', 'seeders'), 'migrations-path': path.resolve('src', 'database', 'migrations') }; ===== Előkészítés ===== npx sequelize-cli init Ha például az **app** könyvtárat választottuk, a következő könyvtárak jönnek létre: app01/ |-app/ | `-models/ | `-index.js |-config/ `-database/ |-migrations/ `-seeders/ ===== .gitignore ===== Futtassuk a következő parancsot: echo " node_modules/ .DS_Store .env" >> .gitignore A .gitignore állomány tartalma, a parancs futtatása után: node_modules/ .DS_Store .env ===== Környezet beállítása ===== ==== A .env fájl ==== NODE_ENV=development PORT=8000 ===== database.json ===== { "development": { "dialect": "sqlite", "storage": "./database.sqlite" }, "test": { "dialect": "sqlite", "storage": "memory" }, "production": { "dialect": "sqlite", "storage": "./database.sqlite" } } ===== Model készítése ===== Készítünk egy modellt, amit használunk majd a programban, és egy migrációs fájlt ami alapján létrehozzuk az adatbázis tábláit. A modell nevét egyesszámban adjuk meg. A migrálás során az adatbázisban a tábla többesszámban jön létre, az első betű nagybetű lesz. npx sequelize-cli model:generate --name Employee --attributes name:string,city:string,salary:decimal Ha újra szeretnék gyártani, akkor a végére: --force A migrációs fájlt nem írja, mindig új jön létre. ===== Migrálás ===== A database.sqlite fájl a migrálás során jön létre. npx sequelize db:migrate Ha szükséges a migráció visszavonható: npx sequelize db:migrate:undo Üres migrációs állományt is létrehozhatunk: npx sequelize-cli migration:create --name valami ===== Express ===== A Sequelize mellett Express-t használjuk. Telepítés: npm install express Létrehozok egy controllers könyvtárat: mkdir api/controllers A gyökérkönyvtárban létrehozok egy server.js fájlt: const express = require('express'); const bodyParser = require('body-parser'); const PORT = process.env.PORT || 3000; const app = express(); app.use(express.json()) require('./routes/index')(app); app.use(bodyParser.json()) app.listen(PORT, () => console.log(`Listening on port: ${PORT}`)) module.exports = app module.exports = app => { const router = require('express').Router() router.get('/', (req, res) => { res.json({messge: 'Dolgozók REST API'}) }) app.use('/api', router) } ===== Futtatás ===== Telepítsük a nodemon programot: npm install nodemon --save-dev Használjuk a package.json fájlban: "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "start": "nodemon server.js" } Indítás: npm start Nézzük meg az eredményt: http://localhost:3000/api ===== Employee routing ===== Vegyük fel a server.js fájlban: require('./routes/employee.routes')(app); A teljes kód: const express = require('express'); const bodyParser = require('body-parser'); const PORT = process.env.PORT || 3000; const app = express(); app.use(express.json()) require('./routes/index')(app); require('./routes/employees.routes')(app); app.use(bodyParser.json()) app.listen(PORT, () => console.log(`Listening on port: ${PORT}`)) module.exports = app Hozzuk létre routingot a **routes** könyvtrában, **employees.routes.js** fájlban: module.exports = app => { const router = require('express').Router() router.get('/', (req, res) => { res.send('get kérés'); }) app.use('/api/employees', router) } ===== Kontroller létrehozása ===== Cseréljük ki a routing bejegyzést, hogy a kontrollert hívja: router.get('/', employees.getEmployees) Teljes kód: module.exports = app => { const router = require('express').Router() const employees = require('../app/controllers/employee.controller') router.get('/', employees.getEmployees) app.use('/api/employees', router) } A kontroller: const { sequelize, Sequelize } = require('../models') const db = require('../models') db.employees = require('../models/employee')(sequelize, Sequelize) const Employee = db.employees exports.getEmployees = (req, res) => { Employee.findAll() .then(data => { res.send(data); }) .catch(err => { res.status(500).send({ message: err.message || "Hiba! Az adatbázis lekérése sikertelen" }) }) } ===== Bővítés Create operációval ===== Vegyünk fel egy új routing bejegyzést: router.post('/', employees.create) Teljes kód: module.exports = app => { const router = require('express').Router() const employees = require('../app/controllers/employee.controller') router.get('/', employees.getEmployees) router.post('/', employees.create) app.use('/api/employees', router) } Most bővítsük a kontrollert: //... exports.create = (req, res) => { if(!req.body.name) { res.status(400).send({ message: "A név megadása kötelező" }) return } const employee = { name: req.body.name, city: req.body.city, salary: req.body.salary } Employee.create(employee) .then( result => { res.send(result) }) } Teljeskód: const { sequelize, Sequelize } = require('../models') const db = require('../models') db.employees = require('../models/employee')(sequelize, Sequelize) const Employee = db.employees exports.getEmployees = (req, res) => { Employee.findAll() .then(data => { res.send(data); }) .catch(err => { res.status(500).send({ message: err.message || "Hiba! Az adatbázis lekérése sikertelen" }) }) } exports.create = (req, res) => { if(!req.body.name) { res.status(400).send({ message: "A név megadása kötelező" }) return } const employee = { name: req.body.name, city: req.body.city, salary: req.body.salary } Employee.create(employee) .then( result => { res.send(result) }) } ===== Update lehetőség ===== exports.update = (req, res) => { const { id } = req.params; if(!req.body.name) { res.status(400).send({ message: "A név megadása kötelező" }) return } const employee = { name: req.body.name, city: req.body.city, salary: req.body.salary }; Employee.update(employee,{ where: { id: id } }) .then((result) => { res.status(200).send({ msg: 'A frissítés sikeres', employee: employee }); }) .catch(err => { res.status(500).sendStatus({ message: err.message || "Hiba! Az adatbázis frissítése sikertelen" }); }); }; ===== Delete lehetőség ===== exports.destroy = (req, res) => { const { id } = req.params; Employee.destroy({ where: { id: id } }) .then(result => { res.status(200).send({Deleted: result}).json() }) .catch(err => { res.status(500).send({error: 'Hiba! A törlés sikertlen!'}).json(); }); }