[[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();
});
}