How to Use Sequelize ORM in NestJS

Updated: January 2, 2024 By: Guest Contributor Post a comment

Introduction

Integrating Sequelize ORM with NestJS leverages the power of type-safe database operations in scalable, server-side applications. This guide illustrates the setup and usage through step-wise code examples.

Setting Up a NestJS Project

Begin by establishing your base NestJS project. If you haven’t already done so, install NestJS CLI and create a new app:

npm i -g @nestjs/cli
nestjs new project-name

Navigate to your project directory:

cd project-name

Installing Sequelize and Dependencies

Install Sequelize, the Sequelize TypeScript typings, and the relevant database driver (e.g., PostgreSQL, MySQL):

npm install --save sequelize sequelize-typescript pg pg-hstore
npm install --save-dev @types/sequelize

Database Connection Configuration

Configure your database connection within the app module:

import { Module } from '@nestjs/common';
import { SequelizeModule } from '@nestjs/sequelize';

@Module({
  imports: [
    SequelizeModule.forRoot({
      dialect: 'postgres',
      host: 'localhost',
      port: 5432,
      username: 'user',
      password: 'password',
      database: 'db',
      models: [], // Add your models here
    }),
  ],
})
export class AppModule {}

Creating a Model

Define your first model with decorators to describe the table:

import { Table, Column, Model } from 'sequelize-typescript';

@Table
export class User extends Model {

  @Column
  firstName: string;

  @Column
  lastName: string;

  // Add other fields and relationships
}

Add the model to your app module’s imports:

imports: [
  SequelizeModule.forRoot({
    //...
    models: [User],
  }),
]

Creating a Service

Develop services to handle business logic:

import { Injectable } from '@nestjs/common';
import { InjectModel } from '@nestjs/sequelize';
import { User } from './user.model';

@Injectable()
export class UserService {
  constructor(
    @InjectModel(User)
    private userModel: typeof User,
  ) {}

  async findAll(): Promise<User[]> {
    return this.userModel.findAll();
  }

  // Define other service methods
}

Implementing Controllers

Use controllers to handle incoming requests and interact with services:

import { Controller, Get } from '@nestjs/common';
import { UserService } from './user.service';
import { User } from './user.model';

@Controller('users')
export class UserController {
  constructor(private readonly userService: UserService) {}

  @Get()
  findAll(): Promise<User[]> {
    return this.userService.findAll();
  }

  // Map more routes to actions
}

Advanced Topics: Associations and Transactions

Dive into advanced features by establishing model associations and managing transactions. Use decorators to define relations:

import { ForeignKey, BelongsTo } from 'sequelize-typescript';
import { Profile } from './profile.model';

@Table
export class User extends Model {
  //...
  
  @ForeignKey(() => Profile)
  @Column
  profileId: number;

  @BelongsTo(() => Profile)
  profile: Profile;
}

Manage complex operations with transactions:

import { Sequelize } from 'sequelize-typescript';

//...

async createUserWithProfile(userData, profileData) {
  return this.sequelize.transaction(async (t) => {
    const user = await this.userModel.create(userData, { transaction: t });
    await user.createProfile(profileData, { transaction: t });
    return user;
  });
}

Handling Migrations

For database changes, Sequelize CLI and migrations keep your schema version-controlled:

npm install --save-dev sequelize-cli
npx sequelize-cli init

Generate and run new migrations:

npx sequelize-cli migration:generate --name add-users-table
npx sequelize-cli db:migrate

Conclusion

Sequelize with NestJS brings robustness to data handling in Node.js applications. By following this guide, you can now configure, use, and manage a type-safe database setup within your NestJS projects.