「项目实战」从0搭建NestJS后端服务(二):数据库选型和Prisma整合

前言

大家好,我是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处理》

我们将探讨:

  • 如何优雅管理多环境配置
  • 跨域问题的三种解决姿势
  • 接口突然挂了的应急方案

🤝 互动时间

新手村同学 :卡在哪一步了?评论区说出你的血泪史!
满级大佬:你们团队怎么处理数据库迁移?求分享最佳实践!

欢迎在评论区分享你的实战经验!

相关推荐
福兮说6 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
郑州光合科技余经理6 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆6667 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
Dovis(誓平步青云)7 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
码艺-Alimjan8 小时前
Vben Admin 新增维吾尔语 Vben-Modal的关键坑之一
前端·javascript·vue.js
可乐鸡翅yeah_8 小时前
hls.js 手动自定义 http 请求 loader,修改请求头实战
开发语言·前端·javascript·网络协议·http·ecmascript·m3u8在线
IT_陈寒8 小时前
Vite静态资源导入这个坑我帮你们踩过了
前端·人工智能·后端
广州华水科技9 小时前
大坝安全监测解决方案:单北斗GNSS形变监测系统应用与维护
前端
yivifu9 小时前
中文古籍电子书注释集成
前端·javascript·python·beautifulsoup·epub
niyongsheng10 小时前
后端零改动,给若依换一套现代化前端
vue.js·开源·node.js