Skip to main content

200. Database

Intro

  • Database | NestJS - A progressive Node.js framework
  • Nest is database agnostic, allowing you to easily integrate with any SQL or NoSQL database.
  • For convenience, Nest provides tight integration with
    • TypeOrm
      • @nestjs/typeorm
    • Sequelize
      • @nestjs/sequelize
    • Mongoose
      • @nestjs/mongoose
    • but still you have the options to use any orm of your choice

Using TypeOrm

  • To begin using typeorm, we first install the required dependencies.
npm i @nestjs/typeorm typeorm pg   
#pg = because we're using postgres, but can be mysql or sth-else
  • Once the installation process is complete, we can import the TypeOrmModule into the root AppModule.
    • To learn more about the options we can pass to TypeOrm check (Site Unreachable)>
//...imports

@Module({
imports: [
CoffesModule,
TypeOrmModule.forRoot({
type: 'postgres',
host: 'localhost',
port: 5432,
username: 'postgres',
password: 'pass123',
database: 'postgres',
autoLoadEntities: true,
synchronize: true, //sync local entity to db entities, warnning must be diabled in production
}),
],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}

TypeOrmModule.forRoot, should only be called once at the root module, for child modules, you need to use .forFeature() method

Is Typeorm Running

  • to check if application, typeorm and db, all are connected and working
    • just run the application with npm run start:dev
    • and you should see no error, but a log specifying typeorm has been initialized
      • ex: TypeOrmModule dependencies initialized

Creating Typeorm Entity

import { Entity, Column, PrimaryGeneratedColumn } from 'typeorm';

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

@Column()
firstName: string;

@Column()
lastName: string;

@Column({ default: true })
isActive: boolean;
}
  • To begin using the User entity, we need to let TypeORM know about it by inserting it into the entities array in the module forRoot() method and forFeature() method of the domain module
@Module({
imports: [
TypeOrmModule.forRoot({
//...
entities: [User],
synchronize: true,
}),
],
})
export class AppModule {}
@Module({
imports: [TypeOrmModule.forFeature([User])],
providers: [UsersService],
controllers: [UsersController],
})
export class UsersModule {}

if you are using autoloadentities:true in .forRoot configurations, you only have to add your entities inside for .forFeature, then nest will take care of the registration. Database | NestJS - A progressive Node.js framework

  • using typorm users repository inside services
@Injectable()
export class UsersService {
constructor(
@InjectRepository(User)
private usersRepository: Repository<User>,
) {}

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

findOne(id: number): Promise<User | null> {
return this.usersRepository.findOneBy({ id });
}

async remove(id: number): Promise<void> {
await this.usersRepository.delete(id);
}
}

you can export TypeOrm repositories so they can be used in another module/service. Database | NestJS - A progressive Node.js framework

Creating DB Relations

//creating 1-m relationship
@Entity()
export class User{

@OneToMany(type => Photo, photo => photo.user)
photos: Photo[];
}
//saving relations
const photo1 = new Photo()
photo1.url = "me.jpg"
await photoRepo.save(photo1)

const photo2 = new Photo()
photo2.url = "me-and-bears.jpg"
await photoRepo.save(photo2)

const user = new User()
user.name = "John"
user.photos = [photo1, photo2]
await userRepo.save(user)
//reading relations
const users = await userRepo.find({
relations: {
photos: true,
},
})

Typeorm Transaction

@Injectable()
export class UsersService {
constructor(private dataSource: DataSource) {}
}
  • run your transaction
async createMany(users: User[]) {
const queryRunner = this.dataSource.createQueryRunner();

await queryRunner.connect();
await queryRunner.startTransaction();
try {
await queryRunner.manager.save(users[0]);
await queryRunner.manager.save(users[1]);

await queryRunner.commitTransaction();
} catch (err) {
// since we have errors lets rollback the changes we made
await queryRunner.rollbackTransaction();
} finally {
// you need to release a queryRunner which was manually instantiated
await queryRunner.release();
}
}

More on Typeorm