prisma generate的原理

2024-08 3

prisma generate 的执行原理涉及到几个关键步骤,包括读取配置、解析模型、生成客户端代码等。以下是该命令的详细执行原理:

1. 读取 Prisma Schema 文件

当我们运行 prisma generate 时,Prisma 会首先查找项目中的 schema.prisma 文件。该文件通常位于 prisma/ 目录下,包含了数据库模型定义、数据源配置(如数据库连接)、生成器配置(如 Prisma Client)等内容。

Prisma 会读取并解析这个文件,以了解我们定义的模型结构、数据源配置,以及生成器的指示。

2. 解析数据源配置

Prisma 解析 datasource 块中的配置,确定与哪个数据库进行交互。这个块通常包含数据库的连接信息,如 providerurl

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

provider 指定了数据库类型(例如 PostgreSQL、MySQL、SQLite 等),而 url 是数据库的连接字符串。其中env("DATABASE_URL")是指配置在根目录下的.env文件的DATABASE_URL指定的数据库连接。具体如下:

# .env文件
# DATABASE_URL 格式为 mysql://用户名:用户密码@数据库IP:数据库端口/需要连接的数据库名
DATABASE_URL="mysql://root:password@127.0.0.1:3306/dataname"

值得一提的是,Prisma的连接池和超时时间也是在DATABASE_URL里配置。配置方式如下:

DATABASE_URL="mysql://root:password@127.0.0.1:3306/dataname?connection_limit=5&pool_timeout=15"

上述配置指定了连接池为5个,超时时间是15秒。
默认连接池大小是num_physical_cpus * 2 + 1,其中,num_physical_cpus表示应用程序运行所在的机器上的物理 CPU 数量。如果你的机器有 四个物理 CPU,你的连接池将包含 九个连接(4 * 2 + 1 = 9)。
默认超时时间是10秒钟。

3. 解析生成器配置

Prisma 还会解析 generator 块,以确定要生成哪些类型的代码。在 prisma generate 的上下文中,最常见的生成器是 prisma-client-js,它负责生成 Prisma Client。

generator client {
  provider = "prisma-client-js"
}

provider 指定了生成器类型, prisma-client-js指示生成器类型是 JavaScript 或 TypeScript 客户端。
除此之外,还有以下可选类型:

  • prisma-client-java:生成一个 Java 语言的客户端。
  • prisma-client-dart:生成一个 Dart 语言的客户端。
  • ...(其他的就不列举了,具体需要的再查看官网)

4. 模型解析与转换

Prisma 解析 model 块中定义的数据库模型。这些模型描述了数据库表的结构,包括字段、数据类型、关系、索引等。

model User {
  id    Int     @id @default(autoincrement())
  name  String
  email String  @unique
  article Article[]
}

上述模型定义了一个User表的结构,其含义如下:
这个 User 模型是使用 Prisma schema 语言定义的,用于描述数据库中的一个 User 表的结构。以下是对这个模型的详细解释:

  1. id Int @id @default(autoincrement()):

    • id: 字段名称,表示用户的唯一标识符。
    • Int: 数据类型,表示这个字段存储整数值。
    • @id: 这个注解将 id 字段标记为主键(Primary Key),确保每个 User 记录都有一个唯一的 id 值。
    • @default(autoincrement()): 这个注解表示 id 字段的默认值是自动递增的。也就是说,每次插入新记录时,id 值会自动增加,无需手动设置。
  2. name String:

    • name: 字段名称,表示用户的名字。
    • String: 数据类型,表示这个字段存储字符串值。
  3. email String @unique:

    • email: 字段名称,表示用户的电子邮件地址。
    • String: 数据类型,表示这个字段存储字符串值。
    • @unique: 这个注解表示 email 字段的值必须是唯一的,不能有两个用户具有相同的电子邮件地址。
  4. article Article[]:

    • article: 字段名称,表示用户发布的文章集合。
    • Article[]: 数据类型,表示一个 Article 模型的数组。这表明 UserArticle 之间存在一对多的关系(即一个用户可以有多篇文章)。
    • 这个字段定义了与 Article 模型的关系,Prisma 会通过这个字段自动管理 UserArticle 之间的关联。

Prisma 会将这些模型转换为内部表示形式,以便生成代码时使用。

5. 生成 Prisma Client 代码

在解析了模型、数据源和生成器配置之后,Prisma 根据这些信息生成客户端代码。这个过程包括:

  • 生成 TypeScript/JavaScript 代码:根据模型生成强类型的 API。每个模型会生成相应的查询、创建、更新、删除等方法。
  • 生成类型定义:对于 TypeScript 项目,Prisma 还会生成类型定义文件(.d.ts),以确保类型安全和自动补全功能。

生成的代码通常位于 node_modules/@prisma/client 目录下。这个客户端库包含了所有与数据库交互的必要逻辑和类型定义。

6. 使用生成的客户端

生成的 Prisma Client 可以在项目中直接导入和使用。开发者可以通过 import { PrismaClient } from '@prisma/client' 来获取 Prisma Client 的实例,并使用它来执行数据库操作。具体例子如下:

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
  const users = await prisma.user.findMany()
  console.log(users)
}

main()
  .catch(e => {
    throw e
  })
  .finally(async () => {
    await prisma.$disconnect()
  })

上述代码中,首先获取Prisma Client的实例 PrismaClient ,然后通过new PrismaClient()来创建与数据库的连接,在main函数中通过prisma.user.findMany() 返回所有用户的记录,最后通过prisma.$disconnect()释放当前与数据库的连接。

7. 清理和验证

最后,prisma generate 还会进行一些清理工作,确保生成的代码是最新的,并且没有过时的代码残留。此外,它还会验证生成的客户端与 Prisma schema 文件的一致性。

  • prisma