天空大作战
94.86M · 2026-02-04
在 NestJS 项目中选择合适的数据库工具对开发效率和代码可维护性至关重要。Prisma 作为新一代类型安全的数据库客户端,凭借其声明式数据模型、 自动生成的查询 API 和 直观的迁移系统,正逐渐成为许多开发者的首选。
本文将演示如何在 NestJS 中集成 Prisma,从初始化配置、定义数据模型,到执行数据库迁移,并基于实际字段说明表结构。同时,也会简要对比传统 ORM(如 TypeORM)的实现方式,帮助你更清晰地理解两者在代码组织与开发体验上的差异。
所有步骤均以可运行为目标,适用于希望快速上手 Prisma 的 NestJS 开发者。
首先,通过以下命令初始化 Prisma
npx prisma init
该命令会自动完成两件事:
1.在项目根目录生成 prisma/ 文件夹(包含 schema.prisma);
2.创建 .env 文件,并预置 DATABASE_URL 环境变量。
同时,你需要手动安装 prisma 作为开发依赖(如果尚未安装):
接下来,修改 .env 文件中的数据库连接地址。
这里以 PostgreSQL 为例,你可以根据自己的数据库类型和配置进行调整:
DATABASE_URL="postgresql://postgres:your_password@localhost:5432/xue?schema=public"
配置完成后,终端通常会显示初始化成功的提示信息,表示 Prisma 已正确设置。
初始化完成后,你会看到 prisma/schema.prisma 文件的默认内容大致如下:
接下来,我们在 schema.prisma 中定义数据模型。
这里以两个常见的表为例:User 和 Post。
model User {
id Int @id @default(autoincrement())
name String @unique @db.VarChar(255)
password String @db.VarChar(255)
createdAt DateTime? @default(now()) @map("created_at") @db.Timestamptz(6)
updatedAt DateTime? @default(now()) @map("updated_at") @db.Timestamptz(6)
posts Post[]
comments Comment[]
likes UserLikePost[]
avatars Avatar[]
files File[]
@@map("users")
}
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
content String? @db.Text
userId Int?
user User? @relation(fields:[userId], references: [id], onDelete: SetNull)
comments Comment[]
tags PostTag[]
likes UserLikePost[]
files File[]
@@index([userId])
@@map("posts")
}
这两个模型将分别映射到数据库中的 users 和 posts 表,并通过外键建立关联。
User 表(数据库表名:users)包含字段
id:主键,自增整数,唯一标识用户。
name:用户名,字符串类型,唯一(不能重复),最大长度 255。
password:密码(通常存储哈希值),字符串类型,最大长度 255。
created_at:用户创建时间,默认为当前时间戳,时区感知(timestamptz)。
updated_at:最后更新时间,默认为当前时间戳,可用于记录修改时间。
Post 表(数据库表名:posts)包含字段
id:主键,自增整数,唯一标识文章。
title:文章标题,字符串类型,最大长度 255。
content:文章内容,文本类型,可为空
user_id:外键,关联 users.id,表示该文章的作者;允许为空(因为 onDelete: SetNull,作者被删时设为 NULL)。
我们定义好数据模型,接着来运行下数据库的迁移命令:
npx prisma migrate dev --name init
其中 --name init 是本次迁移的名称,你可以根据实际变更内容自定义(例如 add_user_and_post),便于后续维护。
迁移成功后,数据库中就会自动创建 users 和 posts 两张表,结构与你在 Prisma Schema 中定义的一致。
讲了那么多,我们来看看没有prisma时会怎么做,对比一下
// user.entity.ts
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column({ unique: true })
email: string;
@Column()
password: string;
}
// auth.service.ts
async register(email: string, password: string) {
const existing = await this.userRepository.findOne({ where: { email } });
if (existing) throw new ConflictException('Email exists');
const user = this.userRepository.create({
email,
password: hash(password),
});
await this.userRepository.save(user);
delete user.password; // 或用 class-transformer 排除
return user;
}
用 Prisma,你只需要写一个 schema.prisma 文件,定义好模型,剩下的增删改查、类型提示、数据库迁移,它都给你生成好。代码少,类型安全,出错早。
不用 Prisma(比如用 TypeORM),你得手动写 Entity 类,加一堆装饰器;查数据要调 Repository 或 QueryBuilder,关联关系靠注解配;改个字段,既要改 Entity,又要写 migration 脚本,还容易漏。
说白了:
一个重配置,一个重编码。选哪个,看你想和谁打交道——和文件打交道,还是和模板代码打交道。
Prisma确实让数据库操作变得更简单、更可预测。
在 NestJS 中集成它,只需几步:定义模型、跑迁移、调用生成的客户端。
没有冗余装饰器,没有手动写 Repository,也没有模糊的类型推断。
如果你受够了在 ORM 里反复写样板代码,只想专注业务逻辑,Prisma 值得一试。
反之,若项目已重度依赖 TypeORM,或需要极细粒度的 SQL 控制,那传统方式也无妨。
工具没有高下,只有合不合适。但至少现在,你知道多了一种更清爽的选择。