前言
大家好,我是elk。之前学习NestJS时一直用TypeORM,但最近发现Prisma这个宝藏ORM框架,论坛里都在说它更香!这次就带大家用实战体验一把NestJS+Prisma组合拳,手把手教你们从零搭建用户模块。
(小声BB:官方文档虽然好,但有些坑还得自己踩过才懂)
🗃️ 数据库选型:MySQL vs PostgreSQL
一句话对比指南
- MySQL:适合快速开发,团队熟悉传统关系型数据库
- PostgreSQL:适合处理复杂查询、地理位置数据,自带Buff加成
举个栗子🌰:
- 用户管理系统 → 选MySQL
- 外卖配送系统(需要地理坐标) → 选PostgreSQL
这次咱们先用MySQL演示,毕竟大多数项目都从这里起步~
Prisma初始化
prisma插件
bash
# 安装核心工具
pnpm install prisma --save-dev
初始化prisma配置
csharp
# 初始化配置文件
pnpm prisma init
此时项目根目录创建了一个prisma目录和一个.env文件,里面有一个schema.prisma
schema.prisma
:指定数据库连接并包含数据库schema.env
:dotenv文件,通常用于将数据库凭据存储在一组环境变量中
安装prisma客户端
为了能够在Nest应用中与数据库进行交互,需要客户端
bash
# 安装客户端(重要!)
pnpm install @prisma/client
配置连接数据库
- schema.prisma
ini
// 定义生成器,指定使用 Prisma Client JS 作为生成的客户端代码
generator client {
// 生成器的提供者,这里使用 Prisma Client JS
provider = "prisma-client-js"
}
// 定义数据源,指定数据库的相关信息
datasource db {
// 数据源的提供者,这里使用 MySQL 数据库
provider = "mysql"
// 数据库连接的 URL,从环境变量中获取
url = env("DATABASE_URL")
}
- .env
ini
# 配置 MySQL 数据库的连接地址,Prisma 将使用该地址连接到数据库
# 数据库的用户名是 root,密码是 123456
# 数据库运行在本地主机上,端口号是 33061
# 要连接的数据库名称是 elk_db
DATABASE_URL="mysql://root:123456@localhost:33061/elk_db"
创建sty_user表
- Schema.prisma
typescript
// 定义生成器,指定使用 Prisma Client JS 作为生成的客户端代码
generator client {
// 生成器的提供者,这里使用 Prisma Client JS
provider = "prisma-client-js"
}
// 定义数据源,指定数据库的相关信息
datasource db {
// 数据源的提供者,这里使用 MySQL 数据库
provider = "mysql"
// 数据库连接的 URL,从环境变量中获取
url = env("DATABASE_URL")
}
// 用户表
model sys_user {
userid BigInt @id @default(autoincrement())
deptid BigInt
username String @unique
nickname String
email String @unique
phone String @unique
sex String @default("0")
avatar String
status String @default("0")
remark String
password String
createdBy String
updatedBy String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
pack.json新增命令
json
"scripts": {
"prisma:pull-DB": "prisma db pull",
"prisma:push-DB": "prisma db push",
"prisma:migrate-create": "prisma migrate dev --name init"
}
- prisma db pull:用与开发环境中,将数据库的表设定,同步到项目中
- prisma db push:用于开发环境中,将项目中表定义的改动,同步到数据库中
- prisma migrate dev --name init:用于开发环境中,将项目中表定义的改动,同步到数据库中,并在项目中生成一条操作记录「数据库迁移,初始化」
执行命令,初始化库
bash
# 在项目终端使用
pnpm prisma:migrate-create
执行完之后,prisma生成一个migrations目录,存放对应的SQL文件
使用vscode中的一个插件 database插件去查看库里是否建立了sty_user表
nest中使用prisma
arduino
# 生成专门的module、service文件
# prisma目录下
nest g mo prisma
nest g s prisma
- prisma.module.ts
kotlin
import { Module, Global } from '@nestjs/common';
import { PrismaService } from './prisma.service';
@Global()
@Module({
providers: [PrismaService],
exports: [PrismaService],
})
export class PrismaModule {}
- prisma.service.ts
typescript
import { INestApplication, Injectable, OnModuleInit } from '@nestjs/common';
import { PrismaClient } from '@prisma/client';
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
// 调用 PrismaClient 的 $connect 方法,连接到数据库
await this.$connect();
}
// 关闭连接
async enableShutdownHooks(app: INestApplication) {
// 监听 Prisma 客户端的 'beforeExit' 事件
this.$on('beforeExit', async () => {
// 调用 NestJS 应用程序的 close 方法,关闭应用程序
await app.close();
});
}
}
user模块调用
bash
# 生成一套CRUD模版
nest g res user
- user.moduel.ts
typescript
import { Module } from '@nestjs/common';
import { UserService } from './user.service';
import { UserController } from './user.controller';
// 引入prisma服务
import { PrismaService } from '../../prisma/prisma.service';
@Module({
controllers: [UserController],
providers: [UserService, PrismaService],
})
export class UserModule {}
- user.service.ts
typescript
import { Injectable } from '@nestjs/common';
import { CreateUserDto } from './dto/create-user.dto';
import { UpdateUserDto } from './dto/update-user.dto';
// 引入prisma服务
import { PrismaService } from '../../prisma/prisma.service';
@Injectable()
export class UserService {
// 注入prisma服务
constructor(private prisma: PrismaService) {}
create(createUserDto: CreateUserDto) {
return 'This action adds a new user';
}
async findAll() {
// 查询用户表
const user = await this.prisma.sys_user.findMany();
console.log('🚀 ~ UserService ~ findAll ~ user:', user);
return `This action returns all user`;
}
findOne(id: number) {
return `This action returns a #${id} user`;
}
update(id: number, updateUserDto: UpdateUserDto) {
return `This action updates a #${id} user`;
}
remove(id: number) {
return `This action removes a #${id} user`;
}
}
📍 下期预告
《从0搭建NestJS后端服务(三):环境配置以及CORS处理》
我们将探讨:
- 如何优雅管理多环境配置
- 跨域问题的三种解决姿势
- 接口突然挂了的应急方案
🤝 互动时间
新手村同学 :卡在哪一步了?评论区说出你的血泪史!
满级大佬:你们团队怎么处理数据库迁移?求分享最佳实践!
欢迎在评论区分享你的实战经验!