下一代 ORM:Prisma
Prisma是什么?
我们在制作什么?
模式
将更改应用到数据库
使用客户端
Prisma是什么?
Prisma是我用过的最好的数据库库之一。简而言之,你编写一个数据库模式,Prisma可以将更改应用到你的数据库,并生成一个专为你的数据库定制的TypeScript客户端库。
我们在制作什么?
在这个例子中,我将使用一个简单的博客应用程序。它有一个User表格和一个Article表。Users可以有多个Articles,每个表Article只有一个作者。
要安装 Prisma,请运行yarn add prisma -D。
模式
prisma在项目根目录下的一个名为 `<path>` 的文件夹中,您可以创建一个名为 `<file>` 的文件schema.prisma。表格的描述(或“模式”)将存储在这里。
Prisma 使用此文件对数据库进行更改,并为我们生成自定义客户端。
migrations暂时可以忽略这个文件夹。
数据源
要指定数据库的位置,您需要创建一个datasource代码块。
在以下代码片段中,我使用了一个 SQLite 数据库(一个轻量级数据库,适合快速测试应用程序,它将数据库存储在单个文件中)。对于 SQLite 数据库的“url”,我指定为database.db。
SQLite
datasource db {
provider = "sqlite"
url = "file:./database.db"
}
Postgres
或者,您可以使用 Postgres 或 MySQL 作为数据库。
由于暴露 Postgres 数据库 URL 会危及数据库安全,我们可以将其存储为环境变量,避免直接写入代码。Prisma 支持.env 文件,它可以从名为 .env 的文件中加载环境变量.env,从而实现可移植的开发环境。
以下是Postgres数据库的代码片段示例:
datasource db {
provider = "postgres"
// Access the DATABASE_URL variable.
url = env("DATABASE_URL")
}
发电机
还记得我说过 Prisma 可以为你生成客户端代码吗?
这段代码片段精确地指定了 Prisma 生成器将遵循的行为。对我来说,它运行得非常完美。
generator client {
provider = "prisma-client-js"
}
转盘是如何运转的……
现在,是时候添加表格了。在这个例子中,我将使用一个简单的博客应用。它有一个User表格和一个Article表。每个表Users可以有多个作者Articles,每个Article作者只能有一个账号。
我们将从每个用户的一些基本信息开始,以便我们熟悉 Prisma 的语法。
要开始创建表的模式,我们声明一个model代码块:
model User {
// Our fields (columns) go here...
}
我们将添加一个 ID 列(整数类型)、一个电子邮件列(字符串类型)和一个姓名列(字符串类型)。
model User {
id Int
email String
name String
}
因为我们希望 ID 可以被索引,所以我们会添加@id装饰器。这是一个简单的应用,因此我们会让它的值对每个用户自动递增。
model User {
id Int @id @default(autoincrement())
email String
name String
}
因为我们希望每个用户的电子邮件地址都是唯一的,所以我们会添加@unique装饰器。
model User {
id Int @id @default(autoincrement())
email String @unique
name String
}
现在,我们来构建Article模型。我们将以与之前相同的方式创建一个 ID 字段,并添加标题字段、内容字段以及用于指定文章发布时间的字段。最后,我们将添加一个authorId字段,用于存储文章作者的 ID。
model Article {
id Int @id @default(autoincrement())
authorId Int
title String
content String
publishedAt DateTime
}
我们的文章有一个名为 `<field_name>` 的字段,但如果有一个名为 `<field_name> ` 且类型为 `User` 的authorId字段岂不是更好?使用 Prisma,我们就能实现这一点!author
model Article {
id Int @id @default(autoincrement())
authorId Int
author User
title String
content String
publishedAt DateTime
}
我们还没完成,但也没剩下多少事要做了。
我们只需要使用@relation装饰器即可。
装饰器@relation使用以下语法:
@relation(fields: [authorId], references: [id])
让我们来分析一下。
该fields属性指定引用中哪个字段存储Article作者的 ID。该references属性指定用户表中该fields属性指向的字段。
刚才的描述可能有点啰嗦,所以我直接给你展示一下它在模式图中的样子:
model Article {
id Int @id @default(autoincrement())
authorId Int
author User @relation(fields: [authorId], references: [id])
title String
content String
publishedAt DateTime
}
完美的。
最后一步。由于每篇文章都有作者,因此从逻辑上讲,每个用户都会有多篇文章。我们实际上无法避免将这一点添加到模式中。
为了在我们的模式中反映这一点,我们只需articles向User模型添加一个字段。我们将它的类型设置为Article[]。
model User {
id Int @id @default(autoincrement())
email String @unique
name String
articles Article[]
}
schema.prisma呼!这篇文章到此结束。
最终schema.prisma效果图如下:
datasource db {
provider = "sqlite"
url = "file:./database.db"
}
generator client {
provider = "prisma-client-js"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
articles Article[]
}
model Article {
id Int @id @default(autoincrement())
authorId Int
author User @relation(fields: [authorId], references: [id])
title String
content String
publishedAt DateTime
}
将更改应用到数据库
现在,我们希望 Prisma 将这些更改应用到我们的数据库。这将自动生成自定义客户端 SDK。将更改应用到数据库的过程称为“迁移”。
应用这些更改的命令是:
yarn prisma migrate dev
最后一点dev表明我们正在开发环境中工作。
我们需要为迁移指定一个名称,所以我们就写上initial migration。
如果一切顺利,输出结果将如下所示:
现在,我们准备开始操作数据库了。
使用客户端
现在我们已经生成了客户端代码,可以开始使用 Prisma 了。
如果生成的客户端代码没有显示,请尝试运行以下命令:
yarn prisma generate。
我们将把代码写在一个名为index.js. 的文件中。Prisma 也内置了 Typescript 支持。
要创建 Prisma 客户端的实例,我们PrismaClient从以下位置导入该类@prisma/client:
const { PrismaClient } = require('@prisma/client');
const prisma = new PrismaClient();
由于 Prisma 的客户端是为我们的数据库定制生成的,因此它具有内置的智能感知功能。
让我们来看一些如何使用 Prisma 客户端的例子。
创建用户
首先,我们将创建一个用户。
这很简单:在 Prisma 中创建任何表都可以用以下方式完成prisma.[table name].create()。
prisma.user.create({
data: {
name: 'Michael Fatemi',
email: '<REDACTED>',
},
});
如果我们想要检索为用户自动生成的 ID:
prisma.user.create({
select: {
id: true
},
data: {
name: 'Michael Fatemi',
email: '<REDACTED>',
},
});
创建文章
由于每篇文章都引用一个用户,Prisma 不允许我们手动指定用户authorId,因为这可能会违反 SQL 创建的外键约束。因此,我们必须通过以下语法指定将用户“连接”到文章。
async function createArticle(authorId, title, content) {
prisma.article.create({
data: {
author: {
connect: {
id: authorId,
},
},
content,
title,
publishedAt: new Date(),
},
});
}
列出用户撰写的文章
我们可以这样获取用户数据:
async function getArticles(userId) {
return await prisma.user.findFirst({
select: {
articles: true
},
where: {
id: userId
}
})
}
列出在特定日期之前发表过文章的用户
这在现实世界中可能没什么用,但可以展示 Prisma 的强大功能。
此示例还展示了如何创建比检查值是否相等更复杂的查询。您还可以通过将对象而不是值传递给子句来检查值是否小于 ( lt)、大于 ( gt)、等于 ( ) 或其他情况。eqwhere
async function getUsersWhoWroteAnArticleBefore(date) {
return await prisma.user.findMany({
select: {
id: true,
name: true
},
where: {
articles: {
some: {
publishedAt: {
lt: date
}
}
}
}
})
}
感谢阅读本文,希望对您学习如何使用 Prisma 自动生成代码有所帮助!
文章来源:https://dev.to/myfatemi04/use-prisma-s-powerful-javascript-client-generator-to-write-a-blog-app-18gj


