In this section, we will explore how to use SQL databases with Sequelize, a promise-based Node.js ORM (Object-Relational Mapping) for PostgreSQL, MySQL, MariaDB, SQLite, and Microsoft SQL Server. Sequelize provides a straightforward API for interacting with SQL databases, making it easier to perform CRUD operations and manage database schemas.

Table of Contents

Introduction to Sequelize

Sequelize is a powerful ORM that allows you to interact with SQL databases using JavaScript. It abstracts the complexities of SQL queries and provides a clean and intuitive API for database operations.

Key Features of Sequelize:

  • Promise-based: Sequelize uses promises for asynchronous operations.
  • Supports multiple SQL dialects: PostgreSQL, MySQL, MariaDB, SQLite, and Microsoft SQL Server.
  • Model-based: Define your database schema using models.
  • Associations: Easily define relationships between models.
  • Migrations: Manage database schema changes with migrations.

Setting Up Sequelize

To get started with Sequelize, you need to install Sequelize and the appropriate database driver for your SQL database.

Installation

# Install Sequelize
npm install sequelize

# Install the database driver (e.g., for PostgreSQL)
npm install pg pg-hstore

Initializing Sequelize

Create a new file database.js to initialize Sequelize:

const { Sequelize } = require('sequelize');

// Create a new Sequelize instance
const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'postgres', // Change this to your database dialect
});

// Test the connection
sequelize.authenticate()
  .then(() => {
    console.log('Connection has been established successfully.');
  })
  .catch(err => {
    console.error('Unable to connect to the database:', err);
  });

module.exports = sequelize;

Replace 'database', 'username', and 'password' with your actual database credentials.

Defining Models

Models in Sequelize represent tables in your database. Each model corresponds to a table, and each instance of a model represents a row in that table.

Example Model Definition

Create a new file models/User.js to define a User model:

const { DataTypes } = require('sequelize');
const sequelize = require('../database');

const User = sequelize.define('User', {
  // Define attributes
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    primaryKey: true,
  },
  username: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  email: {
    type: DataTypes.STRING,
    allowNull: false,
    unique: true,
  },
  password: {
    type: DataTypes.STRING,
    allowNull: false,
  },
}, {
  // Other model options
  timestamps: true,
});

module.exports = User;

Performing CRUD Operations

CRUD operations (Create, Read, Update, Delete) are fundamental for interacting with databases. Sequelize makes it easy to perform these operations.

Create

const User = require('./models/User');

// Create a new user
User.create({
  username: 'john_doe',
  email: '[email protected]',
  password: 'securepassword',
}).then(user => {
  console.log('User created:', user.toJSON());
}).catch(err => {
  console.error('Error creating user:', err);
});

Read

// Find a user by primary key
User.findByPk(1).then(user => {
  if (user) {
    console.log('User found:', user.toJSON());
  } else {
    console.log('User not found');
  }
}).catch(err => {
  console.error('Error finding user:', err);
});

Update

// Update a user's email
User.update({ email: '[email protected]' }, {
  where: {
    id: 1,
  },
}).then(([rowsUpdated]) => {
  console.log('Number of rows updated:', rowsUpdated);
}).catch(err => {
  console.error('Error updating user:', err);
});

Delete

// Delete a user
User.destroy({
  where: {
    id: 1,
  },
}).then(() => {
  console.log('User deleted');
}).catch(err => {
  console.error('Error deleting user:', err);
});

Associations

Sequelize supports various types of associations between models, such as one-to-one, one-to-many, and many-to-many relationships.

Example: One-to-Many Association

Define a Post model and associate it with the User model:

const { DataTypes } = require('sequelize');
const sequelize = require('../database');
const User = require('./User');

const Post = sequelize.define('Post', {
  title: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  content: {
    type: DataTypes.TEXT,
    allowNull: false,
  },
}, {
  timestamps: true,
});

// Define the association
User.hasMany(Post, { foreignKey: 'userId' });
Post.belongsTo(User, { foreignKey: 'userId' });

module.exports = Post;

Practical Exercises

Exercise 1: Define a Product Model

Define a Product model with the following attributes:

  • id (primary key, auto-increment)
  • name (string, not null)
  • price (decimal, not null)
  • stock (integer, not null)

Solution:

const { DataTypes } = require('sequelize');
const sequelize = require('../database');

const Product = sequelize.define('Product', {
  id: {
    type: DataTypes.INTEGER,
    autoIncrement: true,
    primaryKey: true,
  },
  name: {
    type: DataTypes.STRING,
    allowNull: false,
  },
  price: {
    type: DataTypes.DECIMAL,
    allowNull: false,
  },
  stock: {
    type: DataTypes.INTEGER,
    allowNull: false,
  },
}, {
  timestamps: true,
});

module.exports = Product;

Exercise 2: Perform CRUD Operations on the Product Model

  1. Create a new product.
  2. Read the product by its primary key.
  3. Update the product's price.
  4. Delete the product.

Solution:

const Product = require('./models/Product');

// Create a new product
Product.create({
  name: 'Laptop',
  price: 999.99,
  stock: 10,
}).then(product => {
  console.log('Product created:', product.toJSON());

  // Read the product by its primary key
  return Product.findByPk(product.id);
}).then(product => {
  if (product) {
    console.log('Product found:', product.toJSON());

    // Update the product's price
    return product.update({ price: 899.99 });
  }
}).then(product => {
  if (product) {
    console.log('Product updated:', product.toJSON());

    // Delete the product
    return product.destroy();
  }
}).then(() => {
  console.log('Product deleted');
}).catch(err => {
  console.error('Error:', err);
});

Summary

In this section, we covered the basics of using SQL databases with Sequelize. We learned how to:

  • Set up Sequelize and connect to a database.
  • Define models to represent database tables.
  • Perform CRUD operations using Sequelize's API.
  • Define associations between models.

By mastering these concepts, you can efficiently interact with SQL databases in your Node.js applications. In the next module, we will explore authentication and authorization techniques in Node.js applications.

Node.js Course

Module 1: Introduction to Node.js

Module 2: Core Concepts

Module 3: File System and I/O

Module 4: HTTP and Web Servers

Module 5: NPM and Package Management

Module 6: Express.js Framework

Module 7: Databases and ORMs

Module 8: Authentication and Authorization

Module 9: Testing and Debugging

Module 10: Advanced Topics

Module 11: Deployment and DevOps

Module 12: Real-World Projects

© Copyright 2024. All rights reserved