跳到主要内容

创建日期:2026-09-08 | 最近更新:2026-09-08 生态版本(2026-09 npm 核对):TypeORM 1.x / @nestjs/typeorm 12、@prisma/client 7.x / Prisma CLI。本文无数据库环境,代码未在本机运行;接线形态为官方长期稳定的写法,以各自官方文档为准。

数据层:TypeORM 与 Prisma,怎么选、怎么接进 Nest

一句话:Nest 不管你怎么连数据库,它只负责把「数据访问对象」变成可注入的 provider。TypeORM 和 Prisma 是两种哲学:TypeORM 从实体代码出发生成表(code-first,装饰器满天飞),Prisma 从 schema 出发生成类型安全的客户端(schema-first)。选型基本是「装饰器 ORM」vs「schema-first + 生成器」之争,不是对错之分。

1. 先分清两种范式

TypeORMPrisma
出发点用 TS 装饰器定义实体,代码即模型schema.prisma 定义模型,生成类型安全客户端
迁移typeorm migration(需自建/同步)prisma migrate(schema 即真相,强迁移工作流)
查询体验Repository/QueryBuilder,接近手写 SQL 的 ORMPrisma Client:全类型安全、自动提示字段、防 typo
关系加载需显式 relations / 注意 N+1include/select 显式、结果强类型
与 Nest 集成@nestjs/typeorm(forRoot + Repository 注入)自写 PrismaService(一层薄封装)
学习曲线ORM 概念多(Entity/Repository/DataSource)schema 学习点集中、Client 上手快

给个人的建议

  • 想要「ORM 自由度 + 熟悉 SQL/ActiveRecord 思路」→ TypeORM
  • 想要「schema 单一事实来源 + 类型安全到爆 + 不想记装饰器」→ Prisma(近年新项目增长明显);
  • 团队已有 DB 领域模型要强约束 → Prisma 的 migrate + 生成更省心。

2. TypeORM 接进 Nest

接线(app.module)

import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { Cat } from './cats/cat.entity.js';

@Module({
imports: [
TypeOrmModule.forRoot({
type: 'postgres', // / mysql / sqlite ...
host: process.env.DB_HOST,
port: Number(process.env.DB_PORT),
username: process.env.DB_USER,
password: process.env.DB_PASS,
database: process.env.DB_NAME,
autoLoadEntities: true, // 由 forFeature 自动收集实体
synchronize: false, // 生产务必 false,用 migration
}),
],
})
export class AppModule {}

特性模块:Repository 注入

// cats.module.ts
import { TypeOrmModule } from '@nestjs/typeorm';
@Module({
imports: [TypeOrmModule.forFeature([Cat])], // 给本模块注册 Cat 的 Repository
controllers: [CatsController],
providers: [CatsService],
})
export class CatsModule {}
// cats.service.ts —— 构造器直接拿到类型化 Repository
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { Cat } from './cat.entity.js';

@Injectable()
export class CatsService {
constructor(
@InjectRepository(Cat)
private readonly catRepo: Repository<Cat>,
) {}

findAll() { return this.catRepo.find(); }
create(data: Partial<Cat>) { return this.catRepo.save(this.catRepo.create(data)); }
}

看懂了吗:@nestjs/typeorm 做的就是把 TypeORM 的 Repository 变成可注入 provider——剩下的全是 TypeORM 自己的 API(.find/.save/.createQueryBuilder/…)。这也是「Nest 只负责接,数据层由你选」的体现。

事务 / 多写一致

async transfer() {
await this.dataSource.transaction(async (manager) => {
await manager.save(...);
await manager.save(...); // 任一失败 → 整体回滚
});
}

3. Prisma 接进 Nest

schema 定义 + 生成

// prisma/schema.prisma
generator client { provider = "prisma-client-js" }
datasource db { provider = "postgresql"; url = env("DATABASE_URL") }

model Cat {
id Int @id @default(autoincrement())
name String
age Int
breed String?
}
npx prisma migrate dev --name init # 生成迁移 + 应用 + 重新生成 client

薄封装 PrismaService(官网推荐姿势)

// prisma/prisma.service.ts
import { Injectable, OnModuleDestroy, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';

@Injectable()
export class PrismaService extends PrismaClient
implements OnModuleInit, OnModuleDestroy {
async onModuleInit() { await this.$connect(); } // 启动连库(呼应篇1生命周期)
async onModuleDestroy() { await this.$disconnect(); } // 优雅断开
}
// cats.service.ts —— 直接用 PrismaClient,类型安全到字段级
@Injectable()
export class CatsService {
constructor(private readonly prisma: PrismaService) {}
findAll() { return this.prisma.cat.findMany({ include: { owner: true } }); }
create(data: CreateCatDto) { return this.prisma.cat.create({ data }); }
}

对比 TypeORM 的 @InjectRepository,Prisma 是一个 PrismaService 管全部模型prisma.cat / prisma.user / …),不需要 per-entity 注册。想限制只能访问部分表,可再按域包 Service。

4. 绕不开的坑(两种都适用)

  1. N+1 查询:TypeORM 默认不加载关联(要 relations),Prisma 不 include 就没有——但循环里逐条查关联就是 N+1。列表接口要么预加载关联、要么用查询构建器/批量 include
  2. 不要把 synchronize: true 带进生产(TypeORM)——改实体自动改表结构,重则丢数据。上 migration
  3. 类型别用 any:DTO → 实体/Client 的参数要过校验(下篇 ValidationPipe 就是干这个的),否则脏数据直接进库。
  4. 连接生命周期:接进 Nest 就一定要在 onModuleInit/$connect + 销毁钩子断开(PrismaService 已示范),别把连接建在模块顶层。
  5. 事务边界别跨 service 乱开:能收进一个事务函数就收,宁可参数传 manager,也别各开各的连接。

5. 怎么选(决策清单)

你的情况倾向
老项目已有 TypeORM / 熟悉装饰器 ORM继续 TypeORM
从零起步、想要强类型 + 省心迁移Prisma
大量复杂原生 SQL / 性能要手控两者都可下探到 raw SQL;TypeORM 的 QueryBuilder 或 prisma.$queryRaw
跟 Nest 生态贴最紧TypeORM 有官方 @nestjs/typeorm 一键;Prisma 是官方文档里同等推荐的一等公民

提醒:TypeORM 版本跨度大(0.3 → 1.x 有破坏性差异)、Prisma 大版本也不断(7.x 已常见)。别背教程里的旧 API,写前打开你 node_modules 里对应版本的文档

关联