.
https://avatars.githubusercontent.com/u/5642440?v=4
Logo Jhonatec

Jhonatan da Silva Reis, 30

Software Engineer, Dev Full Stack

👾
👾
👾
👾
.
/assets/images/certs/ef-logo.png
.
/assets/images/certs/fiap-logo.png
.
/assets/images/certs/hacker-rank-logo.png
.
/assets/images/certs/escola-da-nuvem-logo.png
.
/assets/images/certs/hacker-rank-logo.png
.
/assets/images/certs/hacker-rank-logo.png
.
/assets/images/certs/trybe-logo.png
.
/assets/images/certs/codecademy-logo.png
.
/assets/images/certs/codecademy-logo.png

16

projetos

39

techs

11

tutoriais

Sequelize sem sequela

thumbnail

Repositório

Neste Repositório irei demonstrar como usar o ORM Sequelize em um projeto com NodeJS (com TypeScript) O projeto conta com duas branches para mostrar o uso com foco na lib sequelize-cli que gera migrations e tudo mais E outra branch codando do zero mesmo a model e sincronizando com o banco de dados

Usando sequelize-cli

Nesta branch será dado foco na geração dos arquivos de forma automática pelo console

Clique aqui

Usando Sequelize de forma manual

Nesta branch, criarei o arquivo de Model e usarei alguns passos para sincronizar com o banco

Clique aqui

Em todas as branches

Criarei uma tabela de Users E ReadBooks para compreender um relacionamento entre elas

Usarei as rotas /users e /books para enviar via POST as informações para o banco E o mesmo para o GET em cada uma delas

Usarei a rota GET /report para uma lista de usuários com todos os livros lidos


Curtiu? Deixe uma ⭐ no repositório para fortalecer conteúdos como esse Acesse meu site JhonaTec.dev


Branch Sequelize com CLI

Vamos usar as migrations e configurar o ambiente com calma

Requisitos:

Colocando o ambiente pra rodar

  1. Clone o projeto
git clone git@github.com:jhonatec-dev/desafio-sequelize.git
  1. Na pasta do projeto rode o arquivo docker-compose.yml
docker compose up -d --build

Espere com paciência a subir os Containers 🥸

  1. Code como se não houvesse amanhã! 🤓

Como configurar o Sequelize para Migrations

1. Instale o CLI também (além do sequelize e mysql2)

npm i sequelize-cli

2. Crie um arquivo .sequelizerc

Aqui ele vai informar pro CLI que dentro da pasta src/database é o local onde ele deverá gerar os arquivos database.json é o arquivo de configuração, daqui a pouco vamos falar dele

const path = require("path");

module.exports = {
  config: path.resolve("src", "database", "config", "database.json"),
  "models-path": path.resolve("src", "database", "models"),
  "seeders-path": path.resolve("src", "database", "seeders"),
  "migrations-path": path.resolve("src", "database", "migrations"),
};

4. Inicie o Sequelize

npx sequelize-cli init

3. Atualize seu JSON de conexão com o banco

Abra o arquivo src/database/config/database.json e atualize as infos de conexão, por exemplo:

{
  "development": {
    "username": "root",
    "password": "root_password",
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mysql"
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mysql"
  }
}

4. Crie o banco de dados:

Rode para criar o Banco de Dados!

npx sequelize-cli db:create

5. Crie sua primeira Migration

Rode o comando de exemplo:

npx sequelize-cli model:generate --name User --attributes name:string,age:integer

Com isso, alguns arquivos serão criados, um na pasta src/database/migrations com o nome da tabela Users Outro na pasta src/database/models para ser usado mais tarde na aplicação

5.1 Crie a Migration Book

Rode o comando:

npx sequelize-cli model:generate --name Book --attributes title:string,userId:integer

Agora vamos alterar os arquivos, começando com a Migration de Books na pasta src/database/migrations/book.js:

//... RESTO DO ARQUIVO ...
      userId: {
        type: Sequelize.INTEGER,
        allowNull: false,
        references: {
          model: 'Users',
          key: 'id'
        }
      },

//... RESTO DO ARQUIVO ...

Assim, o campo passa a ser obrigatório e faz referência à tabela de Users, onde o campo Book.idUser = User.id

Alterando os Models

Vamos começar com a Model de Book src/database/models/book.js:

// ... RESTO DO ARQUIVO ...
    static associate(models) {
      // define association here
      Book.belongsTo(models.User, {
        foreignKey: 'userId',
        as: 'user'
      });
    }
// ... RESTO DO ARQUIVO ...

Por fim, o Model de User src/database/models/user.js:

// ... RESTO DO ARQUIVO ...
       static associate(models) {
      // define association here
      User.hasMany(models.Book, {
        foreignKey: 'userId',
        as: 'books'
      });
    }
// ... RESTO DO ARQUIVO ...

6. Rode as Migrations

Comando:

npx sequelize-cli db:migrate

O PULO DO GATO ⏏️ 🐈 (se der problema usando Docker 🐋)

Provavelmente seu banco estará criado agora, com a tabela(s) da pasta de migrations… Mas quando você chamar na aplicação, a coisa dá erro como se o HOST do arquivo .json estivesse errado. Mas não está!

O que acontece é que quando for executado na aplicação, a chave host deve ter o valor de 'mysql' e vamos fazer isso manualmente no arquivo src/database/models/index.js:

"use strict";

const fs = require("fs");
const path = require("path");
const Sequelize = require("sequelize");
const process = require("process");
const basename = path.basename(__filename);
const env = process.env.NODE_ENV || "development";
const config = require(__dirname + "/../config/database.json")[env];
const db = {};

// Em caso de Docker 🐋🐋
const dotenv = require('dotenv');
dotenv.config();
// nome do serviço do banco de dados no docker-compose.yml
// ou no arquivo .env (por isso o dotenv.config())
config.host = process.env.DB_HOST; 

let sequelize;
if (config.use_env_variable) {
  sequelize = new Sequelize(process.env[config.use_env_variable], config);
} else {
  sequelize = new Sequelize(config.database, config.username, config.password, config);
}

// .... RESTO DO ARQUIVO ....

Usando o model gerado

Agora vamos a um exemplo de código usando o model da pasta src/database/models:

import { DataTypes } from "sequelize";
import db from "./database/models"; // está no arquivo src/database/models/index.js
import user from "./database/models/user"; // model gerado ao rodar o sequelize-cli model:generate
import book from "./database/models/book"; // model gerado ao rodar o sequelize-cli model:generate

// Defining the model passing the sequelize instance and the data types
const UserModel = user(db.sequelize, DataTypes);
const BooksModel = book(db.sequelize, DataTypes);
// Defining Relationship (because somehow doesn't work in associate alone)
UserModel.hasMany(BooksModel, { as: "books" });
BooksModel.belongsTo(UserModel, { as: "user" });

// método de exemplo já usando um método POST na rota /user
app.post("/users", async (req, res) => {
  const { name, age } = req.body;
  try {
    // padrão do arquivo gerado pelo CLI é receber um objeto do tipo Sequelize e um DataTypes
    const model = user(db.sequelize, DataTypes);
    // usando a instância do Model de Users para salvar no Banco
    const newPerson = await model.create({ name, age });
    res.status(201).send(newPerson);
  } catch (error) {
    res.status(500).send({
      message: "Unable to create a new user",
      error,
    });
  }
});

O arquivo src/server.ts já contém a forma de uso com rotas definidas de forma bem simples e objetiva.

Execute com npm run dev

Fique à vontade para adaptar com sua realidade.


Branch manual com TypeScript 💙

Requisitos:

Colocando o ambiente pra rodar

  1. Clone o projeto
git clone git@github.com:jhonatec-dev/desafio-sequelize.git
  1. Na pasta do projeto rode o arquivo docker-compose.yml

É de extrema importância lembrar de informar o nome da base de dados já no arquivo do docker-compose.yml

docker compose up -d --build
  1. Espere com paciência a subir o DB e o BACK 🥸

  2. Code como se não houvesse amanhã! 🤓


Criando os arquivos

1. Crie um arquivo para servir de conexão

Criei meu arquivo em src/config/database.ts

2. Crie sua Model User src/models/User.model.ts

Aqui usei a documentação do Sequelize para criar os campos usando como base minha Interface já definida para uso na aplicação

// Gerar Model para Sequelize usando o type User
import { sequelize } from "../config/database";
import { User } from "../interfaces/User";

import {
  CreationOptional,
  DataTypes,
  InferAttributes,
  InferCreationAttributes,
  Model,
} from "sequelize";

class UserModel
  extends Model<InferAttributes<UserModel>, InferCreationAttributes<UserModel>>
  implements User
{
  declare id: CreationOptional<number>;
  declare name: string;
  declare age: number;
}

UserModel.init(
  {
    id: {
      type: DataTypes.INTEGER,
      autoIncrement: true,
      primaryKey: true,
    },
    name: {
      type: DataTypes.STRING,
      allowNull: false,
    },
    age: {
      type: DataTypes.INTEGER,
      allowNull: false,
    },
  },
  {
    sequelize,
    tableName: "Users",
  }
);

export { UserModel };

3. Crie sua Model Book src/models/Books.model.ts

Aqui usei a documentação do Sequelize para criar os campos usando como base minha Interface já definida para uso na aplicação

4. Sincronize os models com o banco de dados

No arquivo src/server.ts por exemplo, chame a função sequelize.sync() para que os modelos sejam enviados em forma de criação de tabelas para o banco

import cors from "cors";
import dayjs from "dayjs";
import express, { Application } from "express";
import { BookModel } from "./models/Book.model";
import { UserModel } from "./models/User.model";

// Sincronizando o Sequelize com o banco de dados
import { sequelize } from "./config/database";
sequelize.sync();
UserModel.hasMany(BookModel, { as: "books", foreignKey: "userId" });
BookModel.belongsTo(UserModel, { as: "user", foreignKey: "userId" });

// ... RESTO DO ARQUIVO ...

O arquivo src/server.ts já contém a forma de uso com rotas definidas de forma bem simples e objetiva.

Execute com npm run dev

Fique à vontade para adaptar com sua realidade.

A P R O V E I T E

Curtiu? Deixe uma ⭐️ no Repositório pra fortalecer mais conteúdos como esse!

Repositório