内省
使用 Prisma ORM 内省数据库
为了本指南的目的,我们将使用一个包含三个表的演示 SQL schema
CREATE TABLE User (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(255),
email VARCHAR(255) UNIQUE NOT NULL
);
CREATE TABLE Post (
id INTEGER PRIMARY KEY AUTO_INCREMENT 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 User(id)
);
CREATE TABLE Profile (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
bio TEXT,
userId INTEGER UNIQUE NOT NULL,
FOREIGN KEY (userId) REFERENCES User(id)
);
展开以查看表的图形概述
User
列名 | 类型 | 主键 | 外键 | 必填 | 默认值 |
---|---|---|---|---|---|
id | INTEGER | ✔️ | 否 | ✔️ | 自增 |
name | VARCHAR(255) | 否 | 否 | 否 | - |
email | VARCHAR(255) | 否 | 否 | ✔️ | - |
Post
列名 | 类型 | 主键 | 外键 | 必填 | 默认值 |
---|---|---|---|---|---|
id | INTEGER | ✔️ | 否 | ✔️ | 自增 |
createdAt | DATETIME(3) | 否 | 否 | ✔️ | now() |
title | VARCHAR(255) | 否 | 否 | ✔️ | - |
content | TEXT | 否 | 否 | 否 | - |
published | BOOLEAN | 否 | 否 | ✔️ | false |
authorId | INTEGER | 否 | ✔️ | ✔️ | false |
Profile
列名 | 类型 | 主键 | 外键 | 必填 | 默认值 |
---|---|---|---|---|---|
id | INTEGER | ✔️ | 否 | ✔️ | 自增 |
bio | TEXT | 否 | 否 | 否 | - |
userId | INTEGER | 否 | ✔️ | ✔️ | - |
作为下一步,你将内省数据库。内省的结果将是你的 Prisma schema 中的一个数据模型。
运行以下命令内省数据库
npx prisma db pull
此命令读取 .env
中定义的 DATABASE_URL
环境变量并连接到你的数据库。连接建立后,它会内省数据库(即读取数据库 schema)。然后,它将数据库 schema 从 SQL 转换为 Prisma 数据模型。
内省完成后,你的 Prisma schema 会更新
数据模型现在看起来与此类似(请注意,模型中的字段已重新排序以提高可读性)
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(0)
content String? @db.Text
published Boolean @default(false)
authorId Int
User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1")
@@index([authorId], map: "authorId")
}
model Profile {
id Int @id @default(autoincrement())
bio String? @db.Text
userId Int @unique(map: "userId")
User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1")
}
model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique(map: "email") @db.VarChar(255)
Post Post[]
Profile Profile?
}
有关 schema 定义的详细信息,请参阅Prisma schema 参考。
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 相关,因为使用小写的关系字段 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(0)
content String? @db.Text
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1")
@@index([authorId], map: "authorId")
}
model Profile {
id Int @id @default(autoincrement())
bio String? @db.Text
userId Int @unique(map: "userId")
user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1")
}
model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique(map: "email") @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 页面了解更多信息。