NestJS 🧑‍🍳 厨子必修课(五):Prisma 集成(上)

1,542 阅读6分钟

1. 前言

在业务逻辑中,数据库操作是非常常见的一部分。前端应用中展示的数据通常都来源于数据库,通过数据库的读写操作,能够为用户提供所需的信息和功能。

Prisma 是一个现代化的 ORM 工具,简化了数据库操作,并提供了强类型支持和自动生成的数据库模型。现在将探讨如何将 Prisma 集成到项目中,并如何利用其功能来高效管理数据库。

Prisma 目前支持 PostgreSQL、MySQL、SQL Server、SQLite、MongoDB 和 CockroachDB。

这里我们以 PostgreSQL 为例。

欢迎加入技术交流群

image.png

  1. NestJS 🧑‍🍳  厨子必修课(一):后端的本质
  2. NestJS 🧑‍🍳 厨子必修课(二):项目创建
  3. NestJS 🧑‍🍳 厨子必修课(三):控制器
  4. NestJS 🧑‍🍳 厨子必修课(四):服务类
  5. NestJS 🧑‍🍳 厨子必修课(五):Prisma 集成(上)
  6. NestJS 🧑‍🍳 厨子必修课(六):Prisma 集成(下)
  7. NestJS 🧑‍🍳 厨子必修课(七):管道
  8. NestJS 🧑‍🍳 厨子必修课(八):异常过滤器

2. Prisma 初始化

2.1 安装 prisma

npm install prisma -D

2.2 初始化 prisma 设置

npx prisma init

运行完成后,将会在根目录下生成 prisma 目录,里面有一个 schema.prisma 文件用于配置数据库连接和数据库模型,同时在根目录还生成了 .env 文件,用于编写环境变量。

2.3 安装 prisma 客户端

为了能够在 Nest 应用中与数据库进行交互,还要使用 Prisma Client,因此也要安装:

npm install @prisma/client

3. 配置数据库连接

在连接之前需要启动一个数据库,这里使用 docker compose 来实现。

3.1 启动数据库实例

使用 docker compose 创建一个 PostgreSQL 的数据库实例:

# docker-compose.yml

version: '3.8'
services:

  cook-api-1-postgres:
    container_name: cook-api-1-postgres
    image: postgres:14-alpine
    restart: always
    environment:
      - POSTGRES_USER=cook
      - POSTGRES_PASSWORD=cookpassword
    volumes:
      - cook-api-1-data:/var/lib/postgresql/data
    ports:
      - '5432:5432'

volumes:
  cook-api-1-data:

在终端输入以下命令:

docker compose up -d

docker compose up -d.png

输入 docker ps 可以看到 cook-api-1-postgres 数据库实例正在运行:

docker ps 的结果.png

3.2 配置数据库环境变量

在 prisma/schema.prisma 文件中配置 PostgreSQL 数据库连接。找到 datasource 部分并进行如下配置:

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

这表示 prisma 的数据源来自 postgresql,位置从 .env 文件中的 DATABASE_URL 变量中读取。

然后,在项目根目录下的 .env 文件中添加数据库连接 URL:

DATABASE_URL="postgresql://cook:cookpassword@localhost:5432/dev-db"

意思是连接到 localhost:5432 的 dev-db 数据库,用户名为 cook、密码为 cookpassword,这和 docker-compose.yml 中的变量是一致的,否则登录不进去。

3.3 生成模型与迁移

假设佟掌柜让秀才记录的用户信息如下:

User 表 Excel 模拟.png

User 表 Excel 模拟

这些内容在数据库中是一张 User 表,我们需要在 schema.prisma 文件中定义这样的模型:

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
}
  • model User:模型的名称为 User。
  • id:这是一个整型(Int)字段,用来唯一标识每个用户。它被标记为@id,这意味着它是这个模型的主键。@default(autoincrement())表示每当创建一个新记录时,这个字段的值会自动递增。
  • email:这是一个字符串类型(String)的字段,用来存储用户的电子邮件地址。@unique修饰符确保了每个用户的电子邮件地址是唯一的,即不允许有重复的电子邮件地址。
  • name:这是一个可选的字符串字段,用来存储用户的名字。问号(?)表示这个字段可以为空
  • createdAt:这是一个日期时间类型的字段,用来记录用户创建的时间。@default(now())表示每当创建一个新用户时,这个字段会自动设置为当前的日期和时间。

⚠️ 注意:以上属于 Prisma 的模型定义方式,具体可参阅 Prisma 官网。

定义好的模型和数据库还没有关联,因此需要迁移数据库,这样数据库里才有 User 表。

迁移数据库:

npx prisma migrate dev --name init
  • migrate: 这是 Prisma CLI 的一个子命令,用于管理数据库迁移。数据库迁移是数据库架构变更的过程,它允许你将数据库模型的更改应用到实际的数据库中。
  • dev: 这是迁移命令的一个选项,它告诉 Prisma 创建一个开发迁移。开发迁移通常用于本地开发环境,它们不会应用到生产数据库上,而是用于测试和开发目的。
  • --name init: 这是命令的一个参数,用于给迁移命名。在这个例子中,迁移被命名为init,这通常表示这是一个初始化迁移,可能是为了设置数据库的初始状态。

迁移数据库.png

这个命令会根据当前模型生成 SQL 迁移文件,并自动应用到数据库中。现在数据库就和我们的 schema 文件同步完成了,还自动生成了 Prisma Client。

⚠️ 注意:我们也可以使用 npx prisma generate 来手动生成 Prisma Client。

通过 VSC 插件 SQLTools 连接数据库可以看到 User 表已经成功创建了:

SQLTools 插件中查看数据库.png

4. 数据播种

为了验证 Nest 应用能否成功集成了 Prisma,我们将通过 Prisma Client 进行数据播种,看能否与数据库交互。

4.1 可视化数据库

现在运行一下命令可以在 5555 端口看到数据库的内容:

npx prisma studio

打开后,User 表的记录数量为 0。

4.2 创建 seed 文件

首先在 prisma 目录下新建 seed.ts:

import { PrismaClient } from '@prisma/client';

const prisma = new PrismaClient();

async function main() {
  // 删除现有的所有数据 (可选)
  await prisma.user.deleteMany();

  // 创建种子数据
  const users = await prisma.user.createMany({
    data: [
      {
        email: 'alice@example.com',
        name: 'Alice',
      },
      {
        email: 'bob@example.com',
        name: 'Bob',
      },
      {
        email: 'charlie@example.com',
        name: 'Charlie',
      },
    ],
  });

  console.log(`Seeded ${users.count} users`);
}

main()
  .then(async () => {
    await prisma.$disconnect();
  })
  .catch(async (e) => {
    console.error(e);
    await prisma.$disconnect();
    process.exit(1);
  });

调用 prisma 客户端实例(prisma)批量创建 user 用户,这些数据将会真实地记录到数据库中,创建完成后断开数据库连接。

4.3 运行 seed 脚本

在 package.json 中加入脚本:

{
  "scripts": {
+   "seed": "ts-node prisma/seed.ts",
+   "studio": "prisma studio"
  }
}

然后运行:

npm run seed

执行数据播种.png

接着运行:

npm run studio

访问 prisma studio.png

可以看到 User 表中已经有内容了。(id 从 4 开始是因为笔者之前执行过一次了)

5. 总结

通过本篇内容,大家已经学会了如何初始化 Prisma、配置数据库连接以及数据播种,此时 NestJS 已经可以和数据库交互了,在下篇中将会进一步介绍如何在业务逻辑处理中使用 Prisma 来解决实际问题。