Definindo Modelos com Sequelize no Node.js
Um componente chave ao trabalhar com o Sequelize e bancos de dados são os modelos. Eles descrevem a estrutura dos dados armazenados no banco de dados e são o principal meio de interação com o banco.
Existem duas maneiras de definir modelos. A primeira envolve o uso do método define()
. Por exemplo, podemos definir o modelo User
, que representa um usuário:
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
age: {
type: Sequelize.INTEGER,
allowNull: false,
},
});
O primeiro parâmetro do método é o nome do modelo. Nesse caso, o modelo é chamado "user". É importante observar que, se não existir uma tabela correspondente a esse modelo no banco de dados, ela será criada automaticamente. O nome da tabela será o nome do modelo no plural, conforme as regras da língua inglesa. Portanto, neste exemplo, a tabela será chamada "users". Isso deve ser considerado ao nomear os modelos.
O segundo parâmetro do método define()
representa a estrutura do modelo, descrevendo seus campos. Para cada campo, são especificados vários atributos. O atributo type
indica o tipo de dado do campo. Neste exemplo, os campos id
e age
são do tipo INTEGER
, que representa um número inteiro, enquanto o campo name
é do tipo STRING
, que representa uma cadeia de caracteres.
Mapeamento de alguns tipos do Sequelize para tipos SQL:
Sequelize | SQL |
---|---|
Sequelize.STRING | VARCHAR(255) |
Sequelize.STRING.BINARY | VARCHAR BINARY |
Sequelize.TEXT | TEXT |
Sequelize.INTEGER | INTEGER |
Sequelize.FLOAT | FLOAT |
Sequelize.DOUBLE | DOUBLE |
Sequelize.DECIMAL | DECIMAL |
Sequelize.BOOLEAN | TINYINT(1) |
O conjunto completo de tipos e seu mapeamento para tipos SQL pode ser consultado na documentação oficial.
Além disso, para cada campo, é possível definir mais atributos. O atributo allowNull
indica se o campo pode ou não aceitar valores nulos. Por padrão, seu valor é true
, ou seja, o campo pode não ter valor. Definir como false
indica que o campo deve obrigatoriamente ter um valor.
Para o campo id
, também foram definidos mais dois atributos. O atributo autoIncrement: true
indica que o valor do campo será auto-incrementado, enquanto primaryKey: true
define que o campo será a chave primária da tabela.
Segunda maneira de definir um modelo:
class User extends Model {}
User.init(
{
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
age: {
type: Sequelize.INTEGER,
allowNull: false,
},
},
{
sequelize,
modelName: "user",
}
);
Sincronizando com o banco de dados
Antes de interagir com o banco de dados, é necessário garantir que as tabelas estão de acordo com a definição dos nossos modelos. Para sincronizar, usamos o método sync
:
sequelize
.sync()
.then((result) => {
console.log(result);
})
.catch((err) => console.log(err));
O método sync()
alinha a estrutura do banco de dados com a definição dos modelos. Por exemplo, se uma tabela correspondente a um modelo estiver ausente no banco de dados, ela será criada.
Código completo da aplicaçãoÇ
const Sequelize = require("sequelize");
const sequelize = new Sequelize({
dialect: "sqlite",
storage: "programicio.db",
});
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
age: {
type: Sequelize.INTEGER,
allowNull: false,
},
});
sequelize
.sync()
.then((result) => {
console.log(result);
})
.catch((err) => console.log(err));
É importante notar que, além dos campos definidos no modelo, dois campos adicionais serão criados na tabela por padrão: createdAt
e updatedAts
. Eles são do tipo datetime
e registram, respectivamente, o momento da criação e da última atualização de cada linha na tabela.
Por exemplo, ao trabalhar com um banco de dados SQLite, a tabela criada será descrita pelo seguinte script:
CREATE TABLE IF NOT EXISTS `users` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT,
`name` VARCHAR(255) NOT NULL,
`age` INTEGER NOT NULL,
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL
);
Além disso, não é necessário definir o campo id
no modelo, pois o Sequelize criará esse campo automaticamente como chave primária.
Também é possível criar a tabela manualmente no servidor e depois conectá-la ao modelo sem a necessidade de sincronização.
Se esses campos adicionais createdAt
e updatedAt
não forem necessários, é possível desativá-los ao definir o objeto Sequelize usando o parâmetro define: {timestamps: false}
:
const Sequelize = require("sequelize");
const sequelize = new Sequelize({
dialect: "sqlite",
storage: "programicio.db",
define: {
timestamps: false,
},
});
const User = sequelize.define("user", {
id: {
type: Sequelize.INTEGER,
autoIncrement: true,
primaryKey: true,
allowNull: false,
},
name: {
type: Sequelize.STRING,
allowNull: false,
},
age: {
type: Sequelize.INTEGER,
allowNull: false,
},
});
sequelize
.sync()
.then((result) => console.log(result))
.catch((err) => console.log(err));
Se já existir uma tabela no banco de dados que não corresponde à definição do modelo, podemos usar o parâmetro {force: true}
para excluir a tabela existente e criar uma nova com a estrutura correta:
sequelize
.sync({ force: true })
.then((result) => {
console.log(result);
})
.catch((err) => console.log(err));