Atualizado: 02/01/2025

Relacionamento Um-para-Muitos (One-to-Many) com Sequelize no Node.js

Em um exemplo típico, em uma empresa podem trabalhar várias pessoas. Ou seja, temos um relacionamento um-para-muitos (1 empresa - muitos funcionários). Para criar esse tipo de relacionamento no Sequelize, utilizamos o método hasMany(). Por exemplo:

const Sequelize = require("sequelize"); 
// definindo o objeto Sequelize
const sequelize = new Sequelize({
    dialect: "sqlite",
    storage: "programicio.db",
    define: {
    timestamps: false
    }
});
    
// definindo o modelo User
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
    }
});
    
const Company = sequelize.define("company", {
    id: {
    type: Sequelize.INTEGER,
    autoIncrement: true,
    primaryKey: true,
    allowNull: false
    },
    name: {
    type: Sequelize.STRING,
    allowNull: false
    }
});

Company.hasMany(User);
    
sequelize.sync({force:true}).then(()=>{
    console.log("Tables have been created");
}).catch(err => console.log(err));

O método hasMany() é chamado na model principal, que neste caso é Company. No próprio método, passamos a model dependente, User.

Como resultado, o SQLite criará duas tabelas que serão descritas pelo seguinte código SQL:

CREATE TABLE IF NOT EXISTS `companies` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT, 
`name` VARCHAR(255) NOT NULL
);

CREATE TABLE IF NOT EXISTS `users` (
`id` INTEGER PRIMARY KEY AUTOINCREMENT, 
`name` VARCHAR(255) NOT NULL, 
`age` INTEGER NOT NULL, 
`companyId` INTEGER REFERENCES `companies` (`id`) ON DELETE SET NULL ON UPDATE CASCADE
);

Por padrão, na tabela dependente users será criado um campo adicional, cujo nome será o nome da model principal acrescido do sufixo "Id", que neste caso é companyId. Esse campo permitirá que uma linha da tabela users referencie um objeto da tabela companies.

Neste código, vemos que, ao excluir um objeto da tabela companies, os objetos dependentes na tabela users não são removidos. Em vez disso, o campo companyId das linhas associadas será definido como NULL, conforme especificado pela cláusula ON DELETE SET NULL. No entanto, uma estratégia mais comum é a exclusão em cascata, onde a exclusão do objeto principal resulta na exclusão de todos os objetos relacionados. Para configurar isso, o método hasMany() aceita um segundo parâmetro, que é um objeto de configuração do relacionamento entre as models. O parâmetro onDelete define o comportamento na exclusão:

Company.hasMany(User, { onDelete: "cascade" });

Operações Básicas

Agora vamos explorar algumas operações básicas que podem causar dúvidas ao trabalhar com modelos em um relacionamento um-para-muitos.

Ao criar um objeto do modelo dependente, muitas vezes é necessário especificar a referência ao modelo principal relacionado. Para isso, podemos usar a propriedade da model que corresponde ao nome do campo da chave estrangeira na tabela correspondente. No exemplo acima, na tabela users, foi criado o campo companyId para estabelecer a ligação com a tabela companies. Embora essa propriedade não tenha sido explicitamente definida na model Company, ela é criada implicitamente. Veja um exemplo de criação de objetos:

// criando uma empresa
Company.create({ name: "Microsoft"}).then(res => {
    // obtendo o id da empresa criada
    const compId = res.id;
    // criando dois funcionários para essa empresa
    User.create({name:"Tom", age: 39, companyId: compId}).catch(err => console.log(err));
    User.create({name:"Alice", age: 36, companyId: compId}).catch(err => console.log(err));
}).catch(err => console.log(err));

Há outra maneira de adicionar um objeto dependente: por meio da model principal. A model principal possui, implicitamente, um método chamado createNomeDoModeloDependente() (por exemplo, createUser()):

// encontrar a empresa com id=1
Company.findByPk(1).then(company => {
    if (!company) return console.log("Company not found");
    console.log(company);
    // adicionando um objeto para esta empresa
    company.createUser({name:"Bob", age: 43}).catch(err => console.log(err));
}).catch(err => console.log(err));

Na prática, a única diferença em relação à primeira abordagem de criação é que, neste caso, não é necessário especificar o id da model principal.

Para obter todos os objetos dependentes relacionados à model principal, existe o método getNomeDosModelosDependentes (por exemplo, getUsers()). Por exemplo, para obter todos os funcionários da empresa com id=1:

Company.findByPk(1).then(company => {
if (!company) return console.log("Company not found");
company.getUsers()
    .then(users => {
    for (user of users)
        console.log(user.name, " - ", company.name);
    })
    .catch(err => console.log(err));
}).catch(err => console.log(err));

Saída no console:

Tom  -  Microsoft
Alice  -  Microsoft
Bob  -  Microsoft

Todas as outras operações com modelos dependentes relacionados podem ser realizadas da mesma forma que com modelos independentes.

Política de Privacidade

Copyright © www.programicio.com Todos os direitos reservados

É proibida a reprodução do conteúdo desta página sem autorização prévia do autor.

Contato: programicio@gmail.com