In this article, we will be using TypeORM with Nest Js to integrate database with our application. But before starting with TypeORM, let’s have a brief look over the concept of Object-relational mapping(ORM).

Object-relational mapping as a technique for converting data between incompatible type systems using object-oriented programming languages. In other words, ORM is a programming technique in which a metadata descriptor is used to connect object code to a relational database.

Source Wikipedia

Object code is written in object-oriented programming (OOP) languages such as C++, JAVA, etc. We will be using TypeScript for creations of our object-oriented programming.

In addition to the data access technique, ORM also provide
simplified development because it automates object-to-table and table-to-object conversion, resulting in lower development and maintenance costs.

Now, when we have a good idea about what is the notion of ORM is, let’s understand what TypeORM is :-

TypeORM: TypeORM is an ORM that can run in NodeJS, Browser, Cordova, PhoneGap, Ionic, React Native, NativeScript, Expo, and Electron platforms and can be used with TypeScript and JavaScript (ES5, ES6, ES7, ES8).

Topics:

  1. Creating a model( or Table ).
  2. Primary / Auto-generation column.
  3. Relationship between two or more models.
  4. Our Project.

Creating a model/ Table

The first step in the database is to create a table. With TypeORM, we create database tables through models. So models in our app will be our database tables.

Now create a sample model “Cat” for a better understanding.


export class Cat {
    id: number;
    name: string;
    breed: string;
    age: string;
}

Note: The database table is not created for each model but only for those models which are declared as entities. To declare a model as an entity, we just need to add @Entity() decorator before the declaration of the Class defining our model.

In addition to this, we should ideally have columns in our model now because the table which will be generated (because of the model being declared as an entity now) makes no sense without any column in it. To add a data member of a model as a column, we need to decorate a data member with a @Column() decorator.

Let us modify our above model of ‘Cats’ by adding ‘@Entity()’ and ‘@Column()’ decorator.


@Entity()
export class Cat {

    @Column()
    id: number;

    @Column()
    name: string;

    @Column()
    breed: string;
    
    @Column()
    age: string;

}

Primary / auto-generated primary column

Read More:   What I Learned Playing ‘Learn to Code’ Video Games – InApps Technology 2022

For creating a column as a primary key of the database table, we need to use @PrimaryColumn() decorator instead of @Column() decorator. And for the primary column to be self-generated, we need to use @PrimaryGeneratedColumn() instead of @PrimaryColumn().

By making ‘id’ in ‘Cat’ as auto-generated primary key, our Cat model will look like this:


@Entity()
export class Cat {

    @PrimaryGeneratedColumn()
    id: number;

    @Column()
    name: string;

    @Column()
    breed: string;
    
    @Column()
    age: string;

}

Relationship between two or more models

A relationship, in the context of databases, is a situation that exists between two relational database tables when one table has a foreign key that references the primary key of the other table. Relationships allow relational databases to split and store data in different tables while linking disparate data items.

There are 3 types of relationships in relational database design :-

  • One-to-One (implemented by @OneToOne() decorator)
  • One-to-Many / Many-to-One (implemented by @OneToMany() decorator )
  • Many-to-Many (implemented by @ManyToMany() decorator)
One-to-One
One-to-Many
Many-to-Many

Our Project

In this section, we will create a NestJS project in which we will have three tables/entities as follows:

  • UserEntity
  • BookEntity
  • GenreEntity

Relationships between the entities:

  • UserEntity and BookEntity: One-To-Many
  • BookEntity and GenreEntity: Many-To-Many

In simple words, a user can have many books and each book can belong to more than one Genre.

For now, we will create the above-mentioned entities as follows without any relationship between them as follows:

MyProject/db/user.entity.ts


import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, OneToMany } from 'typeorm';
import BookEntity from './book.entity';
@Entity()
export default class UserEntity extends BaseEntity {

  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 500 })
  name: string;
}

MyProject/db/book.entity.ts


import { Entity, PrimaryGeneratedColumn, Column, BaseEntity, ManyToOne, ManyToMany, JoinTable } from 'typeorm';
import UserEntity from './user.entity';
import GenreEntity from './genre.entity';

@Entity()
export default class BookEntity extends BaseEntity 
{
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ length: 500 })
  name: string;
}

MyProject/db/genre.entity.ts


@Entity()
export default class GenreEntity extends BaseEntity {

  @PrimaryGeneratedColumn()
  id: number;

  @Column()
  type: string;

}

For setting up the relation between UserEntity and BookEntity, we have to add the following code in UserEntity and BookEntity Class as follows:

MyProject/db/user.entity.ts


// 1:n relation with bookEntity 
  @OneToMany( type => BookEntity , book => book.user)
  books: BookEntity[];

type => BookEntity is a function that returns the class of the entity with which we want to make our relationship.

Read More:   It Better Not Be Mobile Internet 2.0 – InApps 2022

book => book.user states which column to be used by ‘BookEntity’ to get the associated user.

Now, we have set a One-to-Many relationship from the ‘UserEntity’ side. As One-to-Many is complimentary with Many-to-One, we should state the ‘Many-to-One’ relationship from BookEntity to UserEntity.

MyProject/db/book.entity.ts


// n:1 relation with books
  @ManyToOne(type => UserEntity, user => user.books)
  user: UserEntity;

Similarly, to make a many-to-many relationship between BookEntity and GenreEntity, we have to add the following code:


// n:n relation with genre
  @ManyToMany(type => GenreEntity)
  @JoinTable()
  genres: GenreEntity[];

Here, ‘@JoinTable()’ decorator states that in a many-to-many relationship in BookEntity and GenreEntity, the ownership lies in the BookEntity side.

Now we are done with almost everything related to database and TypeORM. The only thing that remains is to establish a connection with the database. For this purpose, we have to create an ‘ormconfig.json’ file and add the following JSON code in it.

MyProject/ormconfig.json


{
  "type": "sqlite",
  "database": "./database.sqlite",
  "synchronize": "true",
  "entities": [
    "dist/db/entity/**/*.js"
  ],
  "cli": {
    "entitiesDir": "src/db/entity"
  }
}

The first line in the above JSON object specifies that the database we are using is ‘SQLite’.

Now we have to create the NEST controllers and services to handle the requests.

Here are the three DataTransferObjects we will be using in the further code:

MyProject/User/dto/create-user.dto.ts


export default class CreateUserDto {
  readonly name: string;
  readonly books: number[] ;
}

MyProject/User/dto/create-book.dto.ts


export default class CreateBookDto {
  readonly name: string;
  readonly userID: number;
  readonly genreIDs: number[];
}

MyProject/User/dto/create-genre.dto.ts


export default class CreateGenreDto {
  readonly type: string;
}

Below are the Controllers and Services for Users, Books, and Genres which will be handling the requests.

Users

MyProject/User/user.controller.ts


import { Body, Controller, Get, ParseIntPipe, Post, Put } from '@nestjs/common';
import { UserServices } from './user.services';
import CreateUserDto from './dto/create-user.dto';

@Controller('users')
export class UserController {
  constructor(private readonly usersServices: UserServices) {}

//'postUser()' will handle the creating of new User
  @Post('post')
  postUser( @Body() user: CreateUserDto) {
    return this.usersServices.insert(user);
  }
// 'getAll()' returns the list of all the existing users in the database
  @Get()
  getAll() {
    return this.usersServices.getAllUsers();
  }

//'getBooks()' return all the books which are associated with the user 
// provided through 'userID' by the request  
  @Get('books')
  getBooks( @Body('userID', ParseIntPipe) userID: number ) {
    return this.usersServices.getBooksOfUser(userID);
  }
}

Myproject/User/user.service.ts


import { Injectable } from '@nestjs/common';
import UserEntity from '../db/entity/user.entity';
import CreateUserDto from './dto/create-user.dto';
import BookEntity from '../db/entity/book.entity';
import {getConnection} from "typeorm";

@Injectable()
export class UserServices {

  async insert(userDetails: CreateUserDto): Promise<UserEntity> {
    const userEntity: UserEntity = UserEntity.create();
    const {name } = userDetails;
    userEntity.name = name;
    await UserEntity.save(userEntity);
    return userEntity;
  }
  async getAllUsers(): Promise<UserEntity[]> {
    return await UserEntity.find();
  }
  async getBooksOfUser(userID: number): Promise<BookEntity[]> {
    console.log(typeof(userID));
    const user: UserEntity = await UserEntity.findOne({where: {id: userID}, relations: ['books']});
    return user.books;
  }
}

Myproject/User/user.module.ts


import { Module } from '@nestjs/common';
import { UserServices } from './user.services';
import { UserController } from './user.controller';
@Module({
  imports: [],
  controllers: [UserController],
  providers: [UserServices],
})
export class UserModule {}

Genre

Read More:   Python Aims for a 5x Speed Boost – InApps Technology 2022

MyProject/Genre/genre.controller.ts


import { Body, Controller, Get, Post } from '@nestjs/common';
import GenreServices from './genre.services';
import CreateGenreDto from './dto/create-genre.dto';

@Controller('genre')
export default class GenreController {
  constructor(private readonly genreServices: GenreServices) {}
  @Post('post')
  postGenre( @Body() genre: CreateGenreDto) {
    return this.genreServices.insert(genre);
  }
  @Get()
  getAll() {
    return this.genreServices.getAllGenre();
  }
}

MyProject/Genre/genre.services.ts


import { Injectable } from '@nestjs/common';
import CreateGenreDto from './dto/create-genre.dto';
import GenreEntity from '../db/entity/genre.entity';

@Injectable()
export default class GenreServices {
    async insert(genreDetails: CreateGenreDto): Promise<GenreEntity> {

    const genreEntity: GenreEntity = GenreEntity.create();
    const {type} = genreDetails;

    genreEntity.type = type;
    await GenreEntity.save(genreEntity);
    return genreEntity;
  }
  async getAllGenre(): Promise<GenreEntity[]> {
        return await GenreEntity.find();
  }
}

MyProject/Genre/genre.module.ts


import { Module } from '@nestjs/common';
import GenreServices from './genre.services';
import GenreController from './genre.controller';
@Module({
  imports: [],
  controllers: [GenreController],
  providers: [GenreServices],
})
export default class GenreModule {}

Books


MyProject/Books/books.controller.ts

import BookEntity from '../db/entity/book.entity';
import CreateBookDto from './dto/create-book.dto';
import UserEntity from '../db/entity/user.entity';
import { createQueryBuilder, getConnection } from 'typeorm';
import GenreEntity from '../db/entity/genre.entity';

export class BooksService {

  async insert(bookDetails: CreateBookDto): Promise<BookEntity> {
    const { name , userID , genreIDs } = bookDetails;
    const book = new BookEntity();
    book.name = name;
    book.user = await UserEntity.findOne(userID) ;
    book.genres=[];
    for ( let i = 0; i < genreIDs.length ; i++)
    {
             const genre = await GenreEntity.findOne(genreIDs[i]);
             book.genres.push(genre);
    }
    await book.save();
    return book;
  }
  async getAllBooks(): Promise<BookEntity[] > {
    // const user: UserEntity = await UserEntity.findOne({where: {id: 2}, relations: ['books']});
    return BookEntity.find();
  }

MyProject/Books/books.module.ts


import { Module } from '@nestjs/common';
import { BooksService } from './books.service';
import BooksController from './books.controller';
@Module({
  imports: [],
  controllers: [BooksController],
  providers: [BooksService],
})
export default class BooksModule {}

Now, finally, this is the time to integrate everything with ‘app.module.ts’


import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { UserModule } from './User/user.module';
import { TypeOrmModule } from '@nestjs/typeorm';
import UserEntity from './db/entity/user.entity';
import BooksModule from './Books/books.module';
import GenreModule from './Genre/genre.module';
import BookEntity from './db/entity/book.entity';
import GenreEntity from './db/entity/genre.entity';

@Module({
  imports: [UserModule ,
            BooksModule,
            GenreModule,
    TypeOrmModule.forFeature(
      [UserEntity, BookEntity , GenreEntity],
    ),

    TypeOrmModule.forRoot(),
  ],
  controllers: [AppController],
  providers: [AppService],
})
export class AppModule {}

List of Keywords users find our article on Google:

nestjs typeorm
typeorm find order
typeorm many to many
typeorm
nest js tutorial
nestjs tutorial
nestjs reviews
nestjs typeorm insert
typeorm base entity
nestjs many to one
typeorm one to many
nestjs typeorm entity
nest js book
nest js typeorm
typeorm one to one
nest js tutorials
nestjs/typeorm
typeorm findone
nest js orm
typeorm onetoone
typeorm create database

Source: InApps.net

Rate this post
As a Senior Tech Enthusiast, I bring a decade of experience to the realm of tech writing, blending deep industry knowledge with a passion for storytelling. With expertise in software development to emerging tech trends like AI and IoT—my articles not only inform but also inspire. My journey in tech writing has been marked by a commitment to accuracy, clarity, and engaging storytelling, making me a trusted voice in the tech community.

Let’s create the next big thing together!

Coming together is a beginning. Keeping together is progress. Working together is success.

Let’s talk

Get a custom Proposal

Please fill in your information and your need to get a suitable solution.

    You need to enter your email to download

      Success. Downloading...