内省
使用 Prisma ORM 对数据库进行内省
在本指南中,我们将使用一个包含三个表的示例 SQL schema
CREATE TABLE "public"."User" (
id SERIAL PRIMARY KEY NOT NULL,
name VARCHAR(255),
email VARCHAR(255) UNIQUE NOT NULL
);
CREATE TABLE "public"."Post" (
id SERIAL PRIMARY KEY NOT NULL,
title VARCHAR(255) NOT NULL,
"createdAt" TIMESTAMP NOT NULL DEFAULT now(),
content TEXT,
published BOOLEAN NOT NULL DEFAULT false,
"authorId" INTEGER NOT NULL,
FOREIGN KEY ("authorId") REFERENCES "public"."User"(id)
);
CREATE TABLE "public"."Profile" (
id SERIAL PRIMARY KEY NOT NULL,
bio TEXT,
"userId" INTEGER UNIQUE NOT NULL,
FOREIGN KEY ("userId") REFERENCES "public"."User"(id)
);
注意:某些字段用双引号括起来,以确保 PostgreSQL 使用正确的大小写。如果没有使用双引号,PostgreSQL 会将所有内容读取为小写字符。
展开查看表的图形概览
User
列名 | 类型 | 主键 | 外键 | 必需 | 默认值 |
---|---|---|---|---|---|
id | SERIAL | ✔️ | 否 | ✔️ | 自动递增 |
name | VARCHAR(255) | 否 | 否 | 否 | - |
email | VARCHAR(255) | 否 | 否 | ✔️ | - |
Post
列名 | 类型 | 主键 | 外键 | 必需 | 默认值 |
---|---|---|---|---|---|
id | SERIAL | ✔️ | 否 | ✔️ | 自动递增 |
createdAt | TIMESTAMP | 否 | 否 | ✔️ | now() |
title | VARCHAR(255) | 否 | 否 | ✔️ | - |
content | TEXT | 否 | 否 | 否 | - |
published | BOOLEAN | 否 | 否 | ✔️ | false |
authorId | INTEGER | 否 | ✔️ | ✔️ | - |
Profile
列名 | 类型 | 主键 | 外键 | 必需 | 默认值 |
---|---|---|---|---|---|
id | SERIAL | ✔️ | 否 | ✔️ | 自动递增 |
bio | TEXT | 否 | 否 | 否 | - |
userId | INTEGER | 否 | ✔️ | ✔️ | - |
下一步,您将对数据库进行内省。内省的结果将是 Prisma schema 中的数据模型。
运行以下命令对数据库进行内省
npx prisma db pull
此命令读取在 .env
中定义的 DATABASE_URL
环境变量并连接到您的数据库。连接建立后,它将对数据库进行内省(即读取数据库 schema)。然后,它将数据库 schema 从 SQL 转换为您的 Prisma schema 中的数据模型。
内省完成后,您的 Prisma schema 将会更新
数据模型现在看起来与此类似(请注意,模型上的字段已重新排序以提高可读性)
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
authorId Int
User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model Profile {
id Int @id @default(autoincrement())
bio String?
userId Int @unique
User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique @db.VarChar(255)
Post Post[]
Profile Profile?
}
Prisma ORM 的数据模型是您数据库 schema 的声明式表示,并作为生成的 Prisma Client 库的基础。您的 Prisma Client 实例将暴露根据这些模型量身定制的查询。
目前,数据模型存在一些小“问题”
User
关系字段是大写字母,因此不符合 Prisma 的命名约定。为了表达更多“语义”,最好将此字段命名为author
,以更好地描述User
和Post
之间的关系。User
上的Post
和Profile
关系字段以及Profile
上的User
关系字段都是大写字母。为了符合 Prisma 的命名约定,这两个字段都应该小写为post
、profile
和user
。- 即使小写后,
User
上的post
字段命名仍然有点不当。这是因为它实际指的是一个列表的帖子——因此,更好的名称应该是复数形式:posts
。
这些更改与生成的 Prisma Client API 相关,在该 API 中使用小写关系字段 author
、posts
、profile
和 user
会让 JavaScript/TypeScript 开发者感到更自然和符合习惯用法。因此,您可以配置您的 Prisma Client API。
由于关系字段是虚拟的(即它们不直接体现在数据库中),您可以在 Prisma schema 中手动重命名它们,而无需修改数据库
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(6)
content String?
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model Profile {
id Int @id @default(autoincrement())
bio String?
userId Int @unique
user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction)
}
model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique @db.VarChar(255)
posts Post[]
profile Profile?
}
在此示例中,数据库 schema 遵循了命名约定用于 Prisma ORM 模型(只有从内省生成的虚拟关系字段不符合这些约定,需要调整)。这优化了生成的 Prisma Client API 的人体工程学。
使用自定义模型和字段名称
但有时,您可能希望对 Prisma Client API 中暴露的列和表的名称进行额外更改。一个常见的例子是将数据库 schema 中常用的 snake_case 标记转换为 PascalCase 和 camelCase 标记,这对于 JavaScript/TypeScript 开发者来说感觉更自然。
假设您从内省中获得了基于 snake_case 标记的以下模型
model my_user {
user_id Int @id @default(autoincrement())
first_name String?
last_name String @unique
}
如果您为此模型生成了 Prisma Client API,它将在 API 中沿用 snake_case 标记
const user = await prisma.my_user.create({
data: {
first_name: 'Alice',
last_name: 'Smith',
},
})
如果您不想在 Prisma Client API 中使用数据库中的表名和列名,您可以使用@map
和 @@map
进行配置
model MyUser {
userId Int @id @default(autoincrement()) @map("user_id")
firstName String? @map("first_name")
lastName String @unique @map("last_name")
@@map("my_user")
}
通过这种方法,您可以根据自己的喜好命名模型及其字段,并使用 @map
(用于字段名)和 @@map
(用于模型名)指向底层表和列。您的 Prisma Client API 现在如下所示
const user = await prisma.myUser.create({
data: {
firstName: 'Alice',
lastName: 'Smith',
},
})
在配置您的 Prisma Client API 页面了解更多信息。