Sequelize is a promise-based Node.js ORM (Object-Relational Mapping) that makes it easier to work with relational databases such as MySQL. It abstracts the complexities of database interactions and provides a clean API to perform CRUD (Create, Read, Update, Delete) operations, manage associations, and run queries. This chapter will guide you through the process of integrating MySQL with Sequelize in a Node.js application, starting from the basics and moving to more advanced topics.
Before we start using Sequelize, we need to set up our environment. Ensure you have Node.js and MySQL installed on your machine.
You can download Node.js from the official website.
You can download MySQL from the official website.
1.Create a new directory for your project and navigate into it.
mkdir sequelize-mysql-example
cd sequelize-mysql-example
2.Initialize a new Node.js project.
npm init -y
3.Install necessary packages.
npm install express mysql2 sequelize
Open your MySQL client and create a new database.
CREATE DATABASE sequelize_example;
Sequelize requires two main packages: sequelize
and mysql2
.
We have already installed the required packages in the previous section. If you haven’t, run:
npm install sequelize mysql2
Create a new file config/database.js
to set up the Sequelize configuration.
const { Sequelize } = require('sequelize');
// Create a new instance of Sequelize
const sequelize = new Sequelize('sequelize_example', 'root', 'password', {
host: 'localhost',
dialect: 'mysql'
});
module.exports = sequelize;
Replace 'root'
and 'password'
with your MySQL username and password.
Create a new directory models
and add a file User.js
.
const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
}
}, {
tableName: 'users',
timestamps: false
});
module.exports = User;
To sync our model with the database, we need to create a script. Create a file sync.js
.
const sequelize = require('./config/database');
const User = require('./models/User');
sequelize.sync({ force: true }).then(() => {
console.log('Database & tables created!');
});
Run the script to create the table in the database.
node sync.js
Let’s add a new user to the database.
const User = require('./models/User');
async function createUser() {
try {
const user = await User.create({
name: 'John Doe',
email: 'john.doe@example.com'
});
console.log(user.toJSON());
} catch (error) {
console.error('Error creating user:', error);
}
}
createUser();
Retrieve all users from the database.
async function getAllUsers() {
try {
const users = await User.findAll();
console.log(users.map(user => user.toJSON()));
} catch (error) {
console.error('Error fetching users:', error);
}
}
getAllUsers();
Update a user’s email.
async function updateUser() {
try {
const user = await User.findByPk(1);
user.email = 'john.new@example.com';
await user.save();
console.log('User updated:', user.toJSON());
} catch (error) {
console.error('Error updating user:', error);
}
}
updateUser();
Delete a user from the database.
async function deleteUser() {
try {
const user = await User.findByPk(1);
await user.destroy();
console.log('User deleted');
} catch (error) {
console.error('Error deleting user:', error);
}
}
deleteUser();
Sequelize supports various types of associations.
Let’s add a Profile
model and associate it with the User
model.
Create a new file models/Profile.js
.
const { DataTypes } = require('sequelize');
const sequelize = require('../config/database');
const Profile = sequelize.define('Profile', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
bio: {
type: DataTypes.STRING,
allowNull: false
},
userId: {
type: DataTypes.INTEGER,
references: {
model: 'users',
key: 'id'
}
}
}, {
tableName: 'profiles',
timestamps: false
});
module.exports = Profile;
Update models/User.js
to define the association.
const Profile = require('./Profile');
User.hasOne(Profile, {
foreignKey: 'userId',
as: 'profile'
});
Profile.belongsTo(User, {
foreignKey: 'userId',
as: 'user'
});
Sync the models.
const Profile = require('./models/Profile');
sequelize.sync({ force: true }).then(() => {
console.log('Database & tables created!');
});
Sequelize provides a powerful query API.
Fetch users with a specific condition.
async function findUserByEmail(email) {
try {
const user = await User.findOne({ where: { email } });
console.log(user.toJSON());
} catch (error) {
console.error('Error finding user:', error);
}
}
findUserByEmail('john.doe@example.com');
Fetch users with their profiles.
async function findUsersWithProfiles() {
try {
const users = await User.findAll({
include: [{
model: Profile,
as: 'profile'
}]
});
console.log(users.map(user => user.toJSON()));
} catch (error) {
console.error('Error fetching users with profiles:', error);
}
}
findUsersWithProfiles();
Sequelize allows you to define validations and constraints at the model level.
Update models/User.js
to add validations.
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false,
validate: {
notEmpty: true
}
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true,
validate: {
isEmail: true
}
}
}, {
tableName: 'users',
timestamps: false
});
Add unique and foreign key constraints.
const Profile = sequelize.define('Profile', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
bio: {
type: DataTypes.STRING,
allowNull: false
},
userId: {
type: DataTypes.INTEGER,
references: {
model: 'users',
key: 'id'
},
onDelete: 'CASCADE'
}
}, {
tableName: 'profiles',
timestamps: false
});
Hooks are lifecycle events in Sequelize models.
Update models/User.js
to add hooks.
const User = sequelize.define('User', {
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true
},
name: {
type: DataTypes.STRING,
allowNull: false
},
email: {
type: DataTypes.STRING,
allowNull: false,
unique: true
}
}, {
tableName: 'users',
timestamps: false,
hooks: {
beforeCreate: (user, options) => {
user.name = user.name.toUpperCase();
}
}
});
Transactions ensure the integrity of your database operations.
Perform operations within a transaction.
const { Transaction } = require('sequelize');
async function createUserWithProfile() {
const transaction = await sequelize.transaction();
try {
const user = await User.create({
name: 'Jane Doe',
email: 'jane.doe@example.com'
}, { transaction });
const profile = await Profile.create({
bio: 'Hello, I am Jane!',
userId: user.id
}, { transaction });
await transaction.commit();
console.log('User and profile created successfully.');
} catch (error) {
await transaction.rollback();
console.error('Error creating user and profile:', error);
}
}
createUserWithProfile();
Migrations are used to keep track of changes to your database schema over time. Sequelize provides a powerful CLI for managing migrations and seeders.
Install Sequelize CLI globally.
npm install -g sequelize-cli
Initialize Sequelize CLI in your project.
npx sequelize-cli init
This will create the following folders and files:
config/config.json
: Database configuration.migrations/
: Folder for migration files.seeders/
: Folder for seeder files.models/
: Folder for models.Create a new migration to add a Profile
table.
npx sequelize-cli migration:generate --name create-profile-table
This command creates a file in the migrations
folder. Update the file to define the table schema.
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.createTable('profiles', {
id: {
type: Sequelize.INTEGER,
primaryKey: true,
autoIncrement: true
},
bio: {
type: Sequelize.STRING,
allowNull: false
},
userId: {
type: Sequelize.INTEGER,
references: {
model: 'users',
key: 'id'
},
onDelete: 'CASCADE'
},
createdAt: {
allowNull: false,
type: Sequelize.DATE
},
updatedAt: {
allowNull: false,
type: Sequelize.DATE
}
});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.dropTable('profiles');
}
};
Run the migrations to update the database schema.
npx sequelize-cli db:migrate
Seeders allow you to populate your database with initial data.
Create a new seeder to add a user.
npx sequelize-cli seed:generate --name add-users
Update the seeder file.
'use strict';
module.exports = {
up: async (queryInterface, Sequelize) => {
await queryInterface.bulkInsert('users', [{
name: 'Alice',
email: 'alice@example.com',
createdAt: new Date(),
updatedAt: new Date()
}], {});
},
down: async (queryInterface, Sequelize) => {
await queryInterface.bulkDelete('users', null, {});
}
};
Run the seeders to populate the database.
npx sequelize-cli db:seed:all
Sequelize is a powerful ORM for Node.js that simplifies working with relational databases such as MySQL. In this chapter, we covered the basics of setting up a Node.js project with Sequelize, defining models, performing CRUD operations, managing associations, querying data, adding validations and constraints, utilizing hooks, handling transactions, and using migrations and seeders. With this knowledge, you can build robust applications with complex database interactions.Happy coding !❤️