百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

使用 Prisma ORM 构建 NestJS Rest API

ccwgpt 2024-09-27 07:19 48 浏览 0 评论

每日分享最新,最流行的软件开发知识与最新行业趋势,希望大家能够一键三连,多多支持,跪求关注,点赞,留言。

@头条创作挑战赛

了解如何使用 Prisma ORM 构建 NestJS REST API。

NestJS 是一个用于构建后端应用程序的非常可靠的框架。
在这篇文章中,我们将利用我们的 NestJS 知识并将其与 Prisma 结合起来构建一个 RESTful API。这篇文章将有一堆代码,你可以从最后的 Github 链接中获得,或者你也可以一起编写代码。
如果你是 NestJS 的新手,你可以从这篇文章开始,从 NestJS 开始。
什么是Prisma?
Prisma 是下一代对象关系映射器(ORM)。我们可以将它与 Typescript 以及 Javascript 一起使用。它采用了与传统 ORM 有所不同的方法。您可以查看Prisma 的官方网站以获取更多信息。
Prisma 没有使用类,而是使用一种特殊的模式定义语言。
基本上,开发人员使用这种模式定义语言来描述他们的模式。Prisma 运行模式并根据所选数据库编写适当的迁移。它还生成与数据库交互的类型安全代码。
换句话说,Prisma 提供了编写普通 SQL 查询或使用其他 ORM(例如 TypeORM 或 Sequelize)的替代方法。它可以与各种数据库一起使用,例如 PostgreSQL、MySQL、SQLite 甚至 MongoDB。
Prisma 由两个主要部分组成:
Prisma Migrate – 这是 Prisma 提供的迁移工具。它帮助我们保持我们的数据库模式与 Prisma 模式同步。对于我们的架构的每次更改,Prisma Migrate都会生成一个迁移文件。通过这种方式,它还 有助于维护我们的架构可能发生的所有更改的历史记录。
Prisma Client – 这是自动生成的查询生成器。Prisma Client充当我们的应用程序代码和数据库之间的桥梁。它还提供类型安全。
我们将使用 Prisma Migrate 和 Prisma Client 来构建我们的应用程序。
Prisma ORM 有多好?
虽然这可能是一个主观问题,但Prisma 旨在让开发人员更容易处理数据库查询。
任何开发人员都知道,对于大多数应用程序来说,与数据库交互以管理数据是绝对必要的。这种交互可以使用原始查询或ORM 框架(例如 TypeORM)进行。虽然原始查询或查询构建器提供了更多控制,但它们降低了开发人员的整体生产力。
另一方面,ORM 框架通过将数据库模型定义为类来抽象 SQL。这提高了生产力,但大大减少了开发人员的控制。它还导致对象阻抗不匹配。
对象阻抗不匹配是当面向对象的编程语言与关系数据库交互时出现的概念问题。在关系数据库中,数据是标准化的,不同实体之间的链接是通过外键来实现的。但是,对象使用嵌套结构建立相同的关系。编写应用程序代码的开发人员习惯于思考对象及其结构。这在处理关系数据库时会导致不匹配。
Prisma 试图通过提高开发人员的工作效率同时给予他们更多的控制权来解决围绕对象关系映射的问题。
Prisma 如何实现这一点的一些重要方法如下:
它允许开发人员根据对象进行思考。
它有助于避免复杂的模型对象
它有助于使用模式文件 为数据库和应用程序维护单一的事实来源
便于编写 类型安全查询以在编译时捕获错误
更少的样板代码。开发人员可以简单地定义他们的模式,而不用担心特定的 ORM 框架。
设置 NestJS Prisma 项目
有了对 Prisma 的基本了解,我们现在可以开始构建我们的NestJS Prisma REST API。
作为第一步,我们使用 Nest CLI 创建一个新的 NestJS 项目。下面的命令创建一个新的工作 NestJS 项目。

$ nest new nestjs-prisma-demo-app
$ cd nestjs-prisma-demo-app


在下一步中,我们安装Prisma。

$ npm install prisma --save-dev

请注意,这只是一个开发依赖项。
我们将使用Prisma CLI与 Prisma 一起工作。要调用 CLI,我们使用npx如下。

$ npx prisma


激活 Prisma 后,我们将创建初始 Prisma 设置。

$ npx prisma init


此命令在我们的项目目录中创建一个名为的新目录prisma和一个配置文件。
schema.prisma– 从 Prisma 的角度来看,这是最重要的文件。它将出现在prisma目录中。它指定数据库连接,还包含数据库模式。您可以将其视为我们应用程序的核心。
.env– 这就像一个环境配置文件。它存储数据库主机名和凭据。如果它包含数据库凭据,请注意不要将此文件提交到源存储库。
Prisma 数据库连接设置
对于我们的演示NestJS Prisma 应用程序,我们将使用SQLite作为我们的数据库。这是一个易于使用的数据库选项,因为 SQLite 将数据存储在文件中。因此,我们不必设置数据库服务器。
要配置我们的数据库连接,我们必须在schema.prisma文件中进行更改。
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
基本上,我们必须将datasource DB部分中的提供者更改为sqlite。默认情况下,它使用Postgres,但您也可以使用其他数据库解决方案。
第二个更改是在.env文件中。

DATABASE_URL="file:./test.db"


在这里,我们指定数据库文件的路径。文件名为test.db. 你可以随意命名它。
Prisma 迁移命令
现在,我们准备在SQLite数据库中创建表。
为此,我们将首先编写我们的模式。如前所述,模式是在schema.prisma 我们刚才看到的文件中定义的。
我们将更新相同的文件,如下所示:
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Book {
id Int @default(autoincrement()) @id
title String
author String
publishYear Int
}
如您所见,我们使用模式定义语言创建了一个名为Book的模型。它有一些基本属性,例如title,author和publishYear. 是id一个整数并设置为自动递增。
这个模式是我们的应用程序和数据库的唯一真实来源。无需像 TypeORM 等其他 ORM 那样编写任何其他类。在以后的帖子中对此进行更多介绍。
我们现在将使用Prisma Migrate生成迁移文件。

$ npx prisma migrate dev --name init


基本上,此命令会生成 SQL 文件并在配置的数据库上运行它们。您应该能够prisma/migrations在项目的目录中找到以下 SQL 文件。

CREATE TABLE "Book" (
"id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"title" TEXT NOT NULL,
"author" TEXT NOT NULL,
"publishYear" INTEGER NOT NULL
);


test.db此外,将自动创建数据库文件。
安装和生成 Prisma 客户端
我们的数据库现已准备就绪。但是,我们仍然没有办法从我们的应用程序与数据库进行交互。
这就是Prisma Client出现的地方。
但是什么是 Prisma 客户端?
Prisma Client 是一个类型安全的数据库客户端,用于与我们的数据库进行交互。它是使用我们文件中的模型定义生成的。prisma.schema换句话说,客户端公开了特定于我们模型的 CRUD 操作。
我们可以使用以下命令安装 Prisma Client。

$ npm install @prisma/client

在后台,安装步骤也执行prisma generate命令。如果我们对架构进行更改(例如添加字段或新模型),我们可以简单地调用prisma generate命令来相应地更新我们的Prisma 客户端。
安装成功后,Prisma 客户端库node_modules/@prisma/client 会相应更新。
创建数据库服务
在我们的核心应用程序中直接使用Prisma Client API并不是一个好习惯。因此,我们将在另一个服务中抽象出 Prisma Client API。
请参阅文件中的以下代码db.service.ts。
import { INestApplication, Injectable, OnModuleInit } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
@Injectable()
export class DBService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
await this.$connect();
}
async enableShutdownHooks(app: INestApplication) {
this.$on('beforeExit', async () => {
await app.close();
})
}
}
基本上,这是我们应用程序的数据库服务,它扩展了我们在上一步中生成的PrismaClient。它实现了接口OnModuleInit。如果我们不使用OnModuleInit,Prisma 会懒惰地连接到数据库。
Prisma 也有自己的关闭机制,它会破坏数据库连接。因此,我们enableShutdownHooks()在 e 中实现该方法,并在文件DBServic中调用它。main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { DBService } from './db.service';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
const dbService: DBService = app.get(DBService);
dbService.enableShutdownHooks(app)
await app.listen(3000);
}
bootstrap();
创建应用服务
现在我们的数据库服务已经设置好了,我们可以创建实际的应用程序服务了。该服务公开了从数据库中读取、创建、更新和删除书籍的方法。
从名为的文件中查看以下代码book.service.ts:
import { Injectable } from "@nestjs/common";
import { Book, Prisma } from "@prisma/client";
import { DBService } from "./db.service";
@Injectable()
export class BookService {
constructor(private dbService: DBService) {}
async getBook(id: Prisma.BookWhereUniqueInput): Promise<Book | null> {
return this.dbService.book.findUnique({
where: id
})
}
async createBook(data: Prisma.BookCreateInput): Promise<Book> {
return this.dbService.book.create({
data,
})
}
async updateBook(params: {
where: Prisma.BookWhereUniqueInput;
data: Prisma.BookUpdateInput;
}): Promise<Book> {
const { where, data } = params;
return this.dbService.book.update({
data,
where,
});
}
async deleteBook(where: Prisma.BookWhereUniqueInput): Promise<Book> {
return this.dbService.book.delete({
where,
});
}
}
这是一个标准的NestJS 服务,我们在其中注入DBService的一个实例。但是,需要注意的重要一点是使用Prisma Client 生成的 类型,例如BookCreateInput、BookUpdateInput、Book等,以确保我们服务的方法正确键入。无需创建任何额外的 DTO 或接口来支持类型安全。
创建 REST API 控制器
最后,我们可以创建一个 NestJS 控制器来实现 REST API 端点。
从名为的文件中查看以下代码book.controller.ts.
import { Body, Controller, Delete, Get, Param, Post, Put } from "@nestjs/common";
import { Book } from "@prisma/client";
import { BookService } from "./book.service";
@Controller()
export class BookController {
constructor(
private readonly bookService: BookService
) {}
@Get('books/:id')
async getBookById(@Param('id') id: string): Promise<Book> {
return this.bookService.getBook({id: Number(id)});
}
@Post('books')
async createBook(@Body() bookData: {title: string, author: string, publishYear: Number}): Promise<Book> {
const { title, author } = bookData;
const publishYear = Number(bookData.publishYear);
return this.bookService.createBook({
title,
author,
publishYear
})
}
@Put('books/:id')
async updateBook(@Param('id') id: string, @Body() bookData: {title: string, author: string, publishYear: Number}): Promise<Book> {
const { title, author } = bookData;
const publishYear = Number(bookData.publishYear);
return this.bookService.updateBook({
where: {id: Number(id)},
data: {
title,
author,
publishYear
}
})
}
@Delete('books/:id')
async deleteBook(@Param('id') id: string): Promise<Book> {
return this.bookService.deleteBook({
id: Number(id)
})
}
}
在这里,我们也使用Prisma ClientBook生成的类型来实现类型安全。
作为最后一步,我们在 App Module(文件)中配置控制器和服务app.module.ts,以便 NestJS 在应用程序启动期间可以发现它们。
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { BookController } from './book.controller';
import { BookService } from './book.service';
import { DBService } from './db.service';
@Module({
imports: [],
controllers: [AppController, BookController],
providers: [AppService, BookService, DBService],
})
export class AppModule {}
我们的应用程序现已准备就绪。我们可以使用npm run start启动应用程序并在http://localhost:3000/books.
有了这个,我们已经成功地使用 Prisma ORM 创建了一个 NestJS REST API。我们从 Prisma 的基础开始,按照自己的方式编写模式、生成迁移和客户端以与我们的数据库表进行交互。
这篇文章的代码可以在GitHub上找到,以防你想更仔细地研究它。
你是怎么找到这个帖子的?你已经开始在你的项目中使用Prisma ORM了吗?如果是,您如何在可用性方面找到它?还是您在项目中使用其他 ORM 框架?
我很想听听您对此事的看法。所以,请在评论区发表你的看法。如果这篇文章有帮助,请喜欢并分享它。这将有助于帖子覆盖更多人。

相关推荐

一个基于.Net Core遵循Clean Architecture原则开源架构

今天给大家推荐一个遵循CleanArchitecture原则开源架构。项目简介这是基于Asp.netCore6开发的,遵循CleanArchitecture原则,可以高效、快速地构建基于Ra...

AI写代码翻车无数次,我发现只要提前做好这3步,bug立减80%

写十万行全是bug之后终于找到方法了开发"提示词管理助手"新版本那会儿,我差点被bug整崩溃。刚开始两周,全靠AI改代码架构,结果十万行程序漏洞百出。本来以为AI说没问题就稳了,结果...

OneCode低代码平台的事件驱动设计:架构解析与实践

引言:低代码平台的事件驱动范式在现代软件开发中,事件驱动架构(EDA)已成为构建灵活、松耦合系统的核心范式。OneCode低代码平台通过创新性的注解驱动设计,将事件驱动理念深度融入平台架构,实现了业务...

国内大厂AI插件评测:根据UI图生成Vue前端代码

在IDEA中安装大厂的AI插件,打开ruoyi增强项目:yudao-ui-admin-vue31.CodeBuddy插件登录腾讯的CodeBuddy后,大模型选择deepseek-v3,输入提示语:...

AI+低代码技术揭秘(二):核心架构

本文档介绍了为VTJ低代码平台提供支持的基本架构组件,包括Engine编排层、Provider服务系统、数据模型和代码生成管道。有关UI组件库和widget系统的信息,请参阅UI...

GitDiagram用AI把代码库变成可视化架构图

这是一个名为gitdiagram的开源工具,可将GitHub仓库实时转换为交互式架构图,帮助开发者快速理解代码结构。核心功能一键可视化:替换GitHubURL中的"hub...

30天自制操作系统:第六天:代码架构整理与中断处理

1.拆开bootpack.c文件。根据设计模式将对应的功能封装成独立的文件。2.初始化pic:pic(可编程中断控制器):在设计上,cpu单独只能处理一个中断。而pic是将8个中断信号集合成一个中断...

AI写代码越帮越忙?2025年研究揭露惊人真相

近年来,AI工具如雨后春笋般涌现,许多人开始幻想程序员的未来就是“对着AI说几句话”,就能轻松写出完美的代码。然而,2025年的一项最新研究却颠覆了这一期待,揭示了一个令人意外的结果。研究邀请了16位...

一键理解开源项目:两个自动生成GitHub代码架构图与说明书工具

一、GitDiagram可以一键生成github代码仓库的架构图如果想要可视化github开源项目:https://github.com/luler/reflex_ai_fast,也可以直接把域名替换...

5分钟掌握 c# 网络通讯架构及代码示例

以下是C#网络通讯架构的核心要点及代码示例,按协议类型分类整理:一、TCP协议(可靠连接)1.同步通信//服务器端usingSystem.Net.Sockets;usingTcpListene...

从复杂到优雅:用建造者和责任链重塑代码架构

引用设计模式是软件开发中的重要工具,它为解决常见问题提供了标准化的解决方案,提高了代码的可维护性和可扩展性,提升了开发效率,促进了团队协作,提高了软件质量,并帮助开发者更好地适应需求变化。通过学习和应...

低代码开发当道,我还需要学习LangChain这些框架吗?| IT杂谈

专注LLM深度应用,关注我不迷路前两天有位兄弟问了个问题:当然我很能理解这位朋友的担忧:期望效率最大化,时间用在刀刃上,“不要重新发明轮子”嘛。铺天盖地的AI信息轰炸与概念炒作,很容易让人浮躁与迷茫。...

框架设计并不是简单粗暴地写代码,而是要先弄清逻辑

3.框架设计3.框架设计本节我们要开发一个UI框架,底层以白鹭引擎为例。框架设计的第一步并不是直接撸代码,而是先想清楚设计思想,抽象。一个一个的UI窗口是独立的吗?不是的,...

大佬用 Avalonia 框架开发的 C# 代码 IDE

AvalonStudioAvalonStudio是一个开源的跨平台的开发编辑器(IDE),AvalonStudio的目标是成为一个功能齐全,并且可以让开发者快速使用的IDE,提高开发的生产力。A...

轻量级框架Lagent 仅需20行代码即可构建自己的智能代理

站长之家(ChinaZ.com)8月30日消息:Lagent是一个专注于基于LLM模型的代理开发的轻量级框架。它的设计旨在简化和提高这种模型下代理的开发效率。LLM模型是一种强大的工具,可以...

取消回复欢迎 发表评论: