TypeORM with NestJS & PostgreSQL – Guide
1. Installation & Setup
npm install --save @nestjs/typeorm typeorm pg
Enter fullscreen mode
Exit fullscreen mode
import { Module } from ' @nestjs/common ' ;
import { TypeOrmModule } from ' @nestjs/typeorm ' ;
import { User } from ' ./users/user.entity ' ;
import { UsersModule } from ' ./users/users.module ' ;
@ Module ({
imports : [
TypeOrmModule . forRoot ({
type : ' postgres ' ,
host : ' localhost ' ,
port : 5432 ,
username : ' postgres ' ,
password : ' yourpassword ' ,
database : ' testdb ' ,
entities : [ User ],
synchronize : true ,
}),
UsersModule ,
],
})
export class AppModule {}
Enter fullscreen mode
Exit fullscreen mode
2. Defining Entities
@ Entity ()
export class User {
@ PrimaryGeneratedColumn () id : number ;
@ Column ({ unique : true }) email : string ;
@ Column () name : string ;
@ Column ({ nullable : true }) age : number ;
@ CreateDateColumn () createdAt : Date ;
@ UpdateDateColumn () updatedAt : Date ;
@ OneToMany (() => Post , post => post . user )
posts : Post [];
}
Enter fullscreen mode
Exit fullscreen mode
@ Entity ()
export class Post {
@ PrimaryGeneratedColumn () id : number ;
@ Column () title : string ;
@ Column ({ type : ' text ' }) content : string ;
@ ManyToOne (() => User , user => user . posts )
user : User ;
}
Enter fullscreen mode
Exit fullscreen mode
3. Repositories & Services
@ Injectable ()
export class UsersService {
constructor (@ InjectRepository ( User ) private usersRepo : Repository < User > ) {}
findAll () { return this . usersRepo . find ({ relations : [ ' posts ' ] }); }
findOne ( id : number ) { return this . usersRepo . findOne ({ where : { id }, relations : [ ' posts ' ] }); }
create ( userData : Partial < User > ) { const user = this . usersRepo . create ( userData ); return this . usersRepo . save ( user ); }
update ( id : number , userData : Partial < User > ) { return this . usersRepo . update ( id , userData ); }
remove ( id : number ) { return this . usersRepo . delete ( id ); }
}
Enter fullscreen mode
Exit fullscreen mode
4. Controller Example
@ Controller ( ' users ' )
export class UsersController {
constructor ( private usersService : UsersService ) {}
@ Get () getAll () { return this . usersService . findAll (); }
@ Get ( ' :id ' ) getOne (@ Param ( ' id ' ) id : number ) { return this . usersService . findOne ( id ); }
@ Post () create (@ Body () userData : Partial < User > ) { return this . usersService . create ( userData ); }
@ Put ( ' :id ' ) update (@ Param ( ' id ' ) id : number , @ Body () userData : Partial < User > ) { return this . usersService . update ( id , userData ); }
@ Delete ( ' :id ' ) remove (@ Param ( ' id ' ) id : number ) { return this . usersService . remove ( id ); }
}
Enter fullscreen mode
Exit fullscreen mode
5. Query Examples
// QueryBuilder
const users = await this . usersRepo . createQueryBuilder ( ' user ' )
. leftJoinAndSelect ( ' user.posts ' , ' post ' )
. where ( ' user.age > :age ' , { age : 25 })
. orderBy ( ' user.name ' , ' ASC ' )
. getMany ();
// Raw SQL
const result = await this . usersRepo . query ( ' SELECT * FROM "user" WHERE age > $1 ' , [ 25 ]);
Enter fullscreen mode
Exit fullscreen mode
6. Relationships in TypeORM
OneToOne: User → Profile
OneToMany / ManyToOne: User → Posts
ManyToMany: Posts ↔ Tags
@ ManyToMany (() => Tag , tag => tag . posts )
@ JoinTable ()
tags : Tag [];
Enter fullscreen mode
Exit fullscreen mode
7. Transactions
await this . dataSource . transaction ( async ( manager ) => {
await manager . update ( User , { id : 1 }, { age : 30 });
await manager . update ( Post , { id : 5 }, { title : ' Updated ' });
});
Enter fullscreen mode
Exit fullscreen mode
8. Migrations
npx typeorm migration:generate -n CreateUsers
npx typeorm migration:run
npx typeorm migration:revert
Enter fullscreen mode
Exit fullscreen mode
9. Indexes & Constraints
@ Column ({ unique : true }) email : string ;
@ Column ({ nullable : true }) username : string ;
@ Index ( ' idx_user_email ' )
@ Column () email : string ;
Enter fullscreen mode
Exit fullscreen mode
10. Advanced Tips
Use QueryBuilder for complex queries with joins, pagination, filtering.
Avoid N+1 problems with leftJoinAndSelect
.
Use transactions for multi-table operations.
Use migrations in production, not synchronize: true
.
Combine with Redis caching for heavy reads.
Use DTOs + ValidationPipe for input validation.
Top comments (0)