Tartalomjegyzék

< Express

Express - Sequelize

A Sequalize

A Sequelize egy TypeScript és NodeJS alapú ORM a következő adatbázis rendszerek számára:

Webhely:

Példa:

Ebben a Sequelize-t a lehető legegyszerűbben használjuk. Nem használunk migrációt, feltöltőt (seeder). Migráció helyett, a modellen futtatható sync() függvényt használjuk, ami automatikusan létrehozza a modellben megadott táblát, és a későbbiekben is szinkronizálja. A táblák a szerver induláskor azonnal létrejönnek.

Projket

npm init -y
npm install express

Projekt könyvtárszerkezet

empapi/
 |-app/
 |  |-controllers/
 |  |-database/
 |  |-models/
 |  |-routes/
 |  `-indexjs
 |-node_modules/
 |-tools/
 |-.env
 |-.env.example
 |.package.json
 `-pnpm-lock.yaml

Függőségek telepítés

npm install sequelize mariadb sqlite3 dotenv morgan
npm install --save-dev nodemon

Környezet

Feltételezzük, hogy van egy emp nevű adatbázis, egy emp nevű felhasználóval, aki a „titok” jelszóval éri el az adatbázist.

A beállításokat az .env fájlban végezzük, ami alapértelmezetten a projekt gyökérkönyvtárba szokás tenni.

.env.example
APP_PORT=8000
 
DB_DIALECT=mariadb
 
DB_HOST=127.0.0.1
DB_NAME=dbname
DB_USER=dbuser
DB_PASS=dbpassword
 
DB_STORAGE=/ut/vonal

A fájlról készítsünk másolatot .env néven, majd töltsük ki.

.env
APP_PORT=8000
 
DB_DIALECT=mariadb
 
DB_HOST=127.0.0.1
DB_NAME=emp
DB_USER=emp
DB_PASS=titok
 
DB_STORAGE=/ut/vonal

A DB_DIALECT lehetséges értékei esetünkben:

A DB_STORAGE értéke lehet:

A :memory: csak sqlite dialaktus mellett állítható be, és azt jelenti, az adatbázis a memóriában van, az alkalmazás újraindításával törlődik.

Adatbázis

MySQL vagy MariaDB adatbázisban hozzuk lére az adatbázist és a hozzátartozó felhasználót.

create database emp
character set utf8
collate utf8_hungarian_ci;
grant all privileges 
on emp.*
to emp@localhost
identified by 'titok';

A táblák automatikusan létrejönnek a sequelize.sync() függvény hívás hatására az emplyoee.js fájlban.

MariaDB adatbázis elérése

A többféle adatbázist használunk, azt is elég egyetlen fájlban megadni. Itt most csak MariaDB adatbázist használunk, ezért a nevet is database.js lett.

app/database/database.js
const Sequelize = require('sequelize')
require('dotenv').config()
 
const sequelize = new Sequelize(
    process.env.DB_NAME,
    process.env.DB_USER, 
    process.env.DB_PASS,
    {
        host: process.env.DB_HOST,
        dialect: process.env.DB_DIALECT,
        storage: process.env.DB_STORAGE,
        host: process.env.DB_HOST,
        dialectOptions: {}
    }
)
 
module.exports = sequelize

A process.env.DB kezdetű sorok, az adatokat a .env fájlból olvassák.

Model definiálása

app/models/employee.js
const { DataTypes } = require('sequelize')
const sequelize = require('../database/database')
 
                                  //employees nevű tábla jön létre
const Employee = sequelize.define('employees', {
    id: { 
        type: DataTypes.INTEGER,
        autoIncrement: true,
        primaryKey: true
    },
    name: { type: DataTypes.STRING,  allowNull: false  },
    city: { type: DataTypes.STRING,  allowNull: true  },
    salary: { type: DataTypes.DOUBLE , defaultValue: 0 }
})
 
//A model és az adatbázis szinkronizálása, nem erőltetve.
sequelize.sync({
    force: false
})
module.exports = Employee

A „nem erőltetve” annyit jelent, hogy új mezők létrejönnek, de meglévőket nem írja felül. Igény szerint a felülírás is kikényszeríthető a force: true értékkel.

Egyéb típusok

Jelölés Jelentés
DataTypes.INTEGER egész
DataTypes.STRING sztring
DataTypes.DATE Dátum és idő
DataTypes.DOUBLE Double
DataTypes.FLOAT Float
DataTypes.DECIMAL Decimális
DataTypes.BOOLEAN TINYINT(1)

Az itt megadott típusok nem az összes használható típus, csak néhány általánosat került ide. A következő linkeken találunk még használható típusokat:

Kontroller

Az employeecontroller.js állományban hozzuk létre az EmployeeController-t, ami négy függvényt tartalmaz: index(), store(), update() és destroy().

app/controllers/employeecontroller.js
const Employee = require('../models/employee')
 
const EmployeeController = {
    async index(req, res) {
        try {
            const emps = await Employee.findAll()
            res.status(200)
            res.json({
                success: true,
                data: emps
            })
        } catch (error) {
            res.status(500)
            res.send('Hiba')
        }        
    },
    async store(req, res) {
        try {
            const emp = await Employee.create(req.body)
            res.status(201)
            res.json({
                success: true,
                data: emp
            })
        } catch (error) {
            res.status(500)
            res.send('Hiba')
        }        
    },
    async update(req, res) {
        try {
            const id = req.params.id
            const emp = await Employee.update(req.body, {
                where: {id: id}
            })
            res.status(200)
            res.json({
                success: true,
                data: emp
            })
        } catch (error) {
            res.status(500)
            res.send('Hiba')
        }        
    },
    async destroy(req, res) {
        try {
            const id = req.params.id
            const emp = await Employee.destroy({
                where: {id: id}
            })
            res.status(200)
            res.json({
                success: true,
                data: emp
            })
        } catch (error) {
            res.status(500)
            res.send('Hiba')
        }        
    }
}
 
module.exports = EmployeeController

A példában a minden függvényben try…catch szerkezetben valósítjuk meg a kérések feldolgozását és a válaszokat. Ezeket a kivételkezeléseket érdemes külön függvényekbe szerverni.

Routing

Az útválasztó rész, jelenleg négy útvonalat tartalmaz, négy különböző metódussal. Az útválasztáshoz az express útválasztó objektumát használjuk.

app/routes/api.js
const Router = require('express');
const router = Router();
 
const EmployeeController = require('../controllers/employeecontroller')
 
router.get('/employees', EmployeeController.index)
router.post('/employees', EmployeeController.store)
router.put('/employees/:id', EmployeeController.update)
router.delete('/employees/:id', EmployeeController.destroy)
 
module.exports = router

Belépési pont

Az alkalmazás belépési pontja az index.js fájl, amiben az express biztosítja a szerver indulását. Itt vesszük használatba a routes/api.js fájlban készült útválasztó információkat is.

app/index.js
const express = require('express')
const app = new express()
const router = require('./routes/api')
const morgan = require('morgan')
require('dotenv').config()
const PORT = process.env.APP_PORT || 8000
 
app.use(morgan('combined'))
app.use(express.json())
app.use('/api', router)
 
app.listen(PORT, () => {
    console.log(`Listening localhost: ${PORT}`)
})

A .env olvasásához szükség van a dotenv csomag beépítésére, a naplózáshoz a morgan csomagot használjuk. A process.env.APP_PORT a .env fájlból olvassa az alkalmazás által használandó portot.

A package.json

{
  "name": "simpleapi",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "scripts": {
    "start": "nodemon app --watch app"
  },
  "dependencies": {
    "dotenv": "^16.1.4",
    "express": "^4.18.2",
    "mariadb": "^3.1.2",
    "morgan": "^1.10.0",
    "sequelize": "^6.32.0"
  },
  "devDependencies": {
    "nodemon": "^2.0.22"
  }
}

Futtatás

npm start

Teszt

A HTTPie paranccsal:

http localhost:8000/api/employees

Linkek