6月2日 01:25
NestJS 怎么连数据库?TypeORM 和 Prisma 集成实战
NestJS 集成数据库的主流方案有两个:TypeORM(官方推荐,装饰器风格)和 Prisma(类型安全更好,迁移体验好)。选哪个看团队偏好——TypeORM 和 NestJS 风格统一,Prisma 的类型推导更强。
TypeORM 集成
bashnpm install @nestjs/typeorm typeorm pg
配置连接
typescript// app.module.ts import { TypeOrmModule } from '@nestjs/typeorm'; @Module({ imports: [ TypeOrmModule.forRoot({ type: 'postgres', host: process.env.DB_HOST, port: 5432, username: process.env.DB_USER, password: process.env.DB_PASS, database: process.env.DB_NAME, autoLoadEntities: true, synchronize: false, // 生产环境必须 false }), ], }) export class AppModule {}
autoLoadEntities 自动加载注册了 TypeOrmModule.forFeature() 的实体,不用手动列。synchronize: false 防止生产环境自动改表结构(丢数据风险)。
定义实体
typescript// users/user.entity.ts @Entity() export class User { @PrimaryGeneratedColumn('uuid') id: string; @Column({ unique: true }) email: string; @Column() password: string; @CreateDateColumn() createdAt: Date; }
在模块中注册
typescript// users/users.module.ts @Module({ imports: [TypeOrmModule.forFeature([User])], providers: [UsersService], controllers: [UsersController], }) export class UsersModule {}
使用 Repository
typescript// users/users.service.ts @Injectable() export class UsersService { constructor( @InjectRepository(User) private userRepo: Repository<User>, ) {} async findByEmail(email: string) { return this.userRepo.findOne({ where: { email } }); } async create(data: Partial<User>) { const user = this.userRepo.create(data); return this.userRepo.save(user); } }
Prisma 集成
bashnpm install prisma @prisma/client npx prisma init
定义 Schema
prisma// prisma/schema.prisma model User { id String @id @default(uuid()) email String @unique password String createdAt DateTime @default(now()) posts Post[] } model Post { id String @id @default(uuid()) title String content String? authorId String author User @relation(fields: [authorId], references: [id]) createdAt DateTime @default(now()) }
生成迁移并应用
bashnpx prisma migrate dev --name init
在 NestJS 中使用
typescript// prisma/prisma.service.ts @Injectable() export class PrismaService extends PrismaClient implements OnModuleInit { async onModuleInit() { await this.$connect(); } } // users/users.service.ts @Injectable() export class UsersService { constructor(private prisma: PrismaService) {} async findByEmail(email: string) { return this.prisma.user.findUnique({ where: { email } }); } async create(data: { email: string; password: string }) { return this.prisma.user.create({ data }); } }
TypeORM vs Prisma 怎么选
| 维度 | TypeORM | Prisma |
|---|---|---|
| 查询方式 | 装饰器 + Repository | 链式 API(自动补全强) |
| 类型安全 | 需要手动标注 | 自动推导,几乎不需要类型标注 |
| 迁移工具 | 内置但体验一般 | 最好,migrate dev 自动生成 SQL |
| 关联查询 | 容易写出 N+1 | include 语法清晰 |
| 社区 | NestJS 官方推荐 | 增长快,2024-2025 很多人从 TypeORM 迁过来 |
新项目推荐 Prisma——类型安全和迁移体验的优势在项目做大后会越来越明显。已有 TypeORM 的项目不必迁移,两者都能正常工作。
数据库迁移
生产环境绝对不能依赖 synchronize: true(自动同步 schema 到数据库),这会静默删列、改类型,导致数据丢失。
TypeORM 迁移:
bashnpx typeorm migration:generate -n AddUserTable npx typeorm migration:run
Prisma 迁移:
bashnpx prisma migrate dev --name add_user_table # 开发 npx prisma migrate deploy # 生产
migrate dev 生成迁移文件并应用,migrate deploy 只应用已有文件,适合 CI/CD。