Battle of the Node.js ORMs: Sequelize vs TypeORM
Published: 2023-04-07 21:00:56

Popular Object-Relational Mapping (ORM) libraries for Node.js include [Sequelize](https://sequelize.org/) and [TypeORM](https://typeorm.io/). Both of these libraries offer a higher level of abstraction over relational databases and simplify database operations by offering a user-friendly API.

While there are numerous parallels across these libraries, there are also significant variances. Some of the most significant distinctions between Sequelize and TypeORM will be discussed in this post.

### **Language Support**

The language support offered by Sequelize and TypeORM is one of their key distinctions. When compared to TypeORM, Sequelize supports TypeScript as well as JavaScript.

Sequelize may therefore be a better option for you if you're working on a JavaScript-based project. However, if you're using TypeScript, TypeORM might be a better choice.

### **Querying**

Another difference between Sequelize and TypeORM is in how they handle queries. Sequelize uses a query builder, which allows you to construct complex queries using JavaScript or TypeScript. On the other hand, TypeORM uses a repository pattern, which allows you to perform basic CRUD (Create, Read, Update, Delete) operations using methods like **`find`**, **`findOne`**, **`save`**, **`update`**, and **`delete`**.

Both approaches have advantages, however, TypeORM's repository design may be easier to use for simple CRUD operations while Sequelize's query builder mechanism may be better suited for more complex queries.

### **Relationships**

You can specify one-to-many, many-to-many, and one-to-one relationships between tables in your database using both Sequelize and TypeORM. They manage relationships differently, though.

Sequelize defines relationships using a conventional method, in which the foreign key constraint is specified in the migration or model definition. On the other hand, TypeORM employs a more contemporary methodology in which relationships are defined using decorators in your model design.

This indicates that Sequelize might be a better option for you if you want a more conventional way of defining relationships. Nonetheless, TypeORM can be a better choice if you choose a more contemporary strategy.

### **Support for Other Databases**

Their support for different databases is yet another distinction between Sequelize and TypeORM. Despite the fact that both libraries support a variety of databases, Sequelize offers broader support for more databases, such as `MySQL`, `PostgreSQL`, `SQLite`, and `Microsoft SQL Server`. Contrarily, `MySQL`, `PostgreSQL`, `MariaDB`, `SQLite`, `Oracle`, `Microsoft SQL Server`, and `MongoDB` are all supported by TypeORM.

This can be a crucial consideration if you're using a particular database that neither library supports.

## Sample CRUD using both ORMs

## **Sequelize Example**

Here is an example of how to create a model and carry out CRUD operations on a database table using Sequelize:

```js
const { Sequelize, Model, DataTypes } = require('sequelize');

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql'
});

class User extends Model {}
User.init({
  firstName: DataTypes.STRING,
  lastName: DataTypes.STRING,
  email: DataTypes.STRING
}, { sequelize, modelName: 'user' });

(async () => {
  await sequelize.sync();
  const user = await User.create({ firstName: 'John', lastName: 'Doe', email: 'john.doe@example.com' });
  console.log(user.toJSON());
  const users = await User.findAll();
  console.log(users.map(user => user.toJSON()));
})();
```
This code establishes a connection to a MySQL database, defines a `User` model with three characteristics, synchronizes the model with the database, creates a new user record, retrieves all users from the database, and logs the results to the console.

## **TypeORM Example**

Here's an example of using TypeORM to define a model and perform CRUD operations on a database table:

```ts
import { createConnection } from 'typeorm';

@Entity()
class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  firstName: string;

  @Column()
  lastName: string;

  @Column()
  email: string;
}

(async () => {
  const connection = await createConnection();
  const user = new User();
  user.firstName = 'John';
  user.lastName = 'Doe';
  user.email = 'john.doe@example.com';
  await connection.manager.save(user);
  console.log(user);
  const users = await connection.manager.find(User);
  console.log(users);
})();
```
By creating a new user record, building a `User` entity with three properties, extracting all users from the database, and logging the results to the console, this application connects to a normal MySQL database.

As you can see, both Sequelize and TypeORM provide similar APIs for defining models/entities and performing CRUD operations on a database table. However, the syntax and approach are different due to the language and design choices made by each library.

## Sample relationship table using both ORMs

## **TypeORM Example**

Take the `User` and `Post` objects as an example. Each post has a single owner, and each user is permitted to have several posts. Here is how this relationship might be expressed using TypeORM:

```ts
@Entity()
class User {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  name: string;

  @OneToMany(() => Post, post => post.user)
  posts: Post[];
}

@Entity()
class Post {
  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  title: string;

  @Column()
  content: string;

  @ManyToOne(() => User, user => user.posts)
  user: User;
}
```

In the `User` entity, we define a one-to-many relationship with `Post` using the `@OneToMany` decorator. We specify that the relationship is to the `Post` entity and that it's related to the `user` property on the `Post` entity.

In the `Post` entity, we define a many-to-one relationship with `User` using the `@ManyToOne` decorator. We specify that the relationship is to the `User` entity and that it's related to the `posts` property on the `User` entity.

With this setup, we can fetch a user and all their posts like this:

```ts
const user = await connection.manager.findOne(User, 1, { relations: { posts: true } });
```

This will fetch the user with the ID of 1 and eagerly load all their posts.

## **Sequelize Example**

Here's how we can define the same relationship using Sequelize:

```js
const { Sequelize, Model, DataTypes } = require('sequelize');

const sequelize = new Sequelize('database', 'username', 'password', {
  host: 'localhost',
  dialect: 'mysql'
});

class User extends Model {}
User.init({
  name: DataTypes.STRING
}, { sequelize, modelName: 'user' });

class Post extends Model {}
Post.init({
  title: DataTypes.STRING,
  content: DataTypes.STRING
}, { sequelize, modelName: 'post' });

User.hasMany(Post);
Post.belongsTo(User);
```

In this example, we define the `User` and `Post` models using `Model.init`. We then define the relationship between the two models using the `User.hasMany(Post)` and `Post.belongsTo(User)` methods.

With this setup, we can fetch a user and all their posts like this:

```js
const user = await User.findByPk(1, { include: [Post] });
```

This will fetch the user with the ID of 1 and eagerly load all their posts.