likes
comments
collection
share

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

作者站长头像
站长
· 阅读数 20

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

前言

上一篇内容回顾:# MidwayJS 全栈开发(四)ORM 技术选型 。

前面铺垫了很多技术介绍,终于,在本篇我们进入到实战环节:通过 Prisma 和 PostgreSQL 实现 CRUD 打造 RestAPI。


PostgreSQL 准备

对于数据库管理系统,作为全栈的我们选择使用 PostgreSQL

安装 PostgreSQL

首先是安装,大家可以在本地按照网上的教程操作下。(安装教程不做详述,推荐使用 brew install postgresql@15 安装最新版 15.2。)

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

安装完成后,记得按提示将环境变量配置好。这里我们可以输入 psql --version 验证环境配置是否 OK。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

启动 PostgreSQL

我们可以输入 brew services start postgresql@15 启动本地的 PostgreSQL 服务。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

另外,我们可以输入 brew services list 查看 PostgreSQL 的服务状态,确保它处在 started 即表示运行中的状态。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

服务运行OK,但是在使用数据库之前,我们需要创建一个数据库,这样才能在里面创建表,完成增删改查。

创建数据库

我们可以在终端通过全局命令 createdb 创建数据库,库名为 database_development,作为本地开发调试数据库。

createdb database_development

恭喜没有任何提示或报错,那说明执行成功。

接着我们输入 psql database_development 登入进 database_development 数据库。 登入后提示符变成 database_development=#

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

Q:大家或许很奇怪,连接数据库难道不需要用户和密码认证吗?数据库的安全性怎么保证呢?

其实不是的。 我们可以在里面输入 \conninfo 查看此次连接信息。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

可以看到,我们是作为用户(flcwl)登录进来的,默认端口 5432。其实 PostgreSQL 默认会把当前登录电脑系统的账户名称(flcwl)会作为 superuser(超级管理员) 角色创建用户,作为预设,本机无需密码认证

这里,我们可以输入 \du 查看现有的用户角色及其权限信息,得以验证。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

那么我们前面创建数据库,连接数据库的这些操作,其实都是基于 superuser 角色进行的,自然可以一气呵成地操作成功了。

创建用户

从上面可以看到超级管理员 superuser 的权限非常之大,为了安全起见,在实际业务场景中,我们会创建和使用其它用户角色(遵循最小权限原则)连接和操作数据库。

首先我们创建一个用户:

  • 用户名就叫 testuser,密码为 12345678
  • 并赋予创建数据库的权限 CREATEDB,方便后续 Prisma ORM 使用;
CREATE USER testuser WITH PASSWORD '12345678';
ALTER ROLE testuser CREATEDB;

可以看到,testuser 用户创建成功了,并且拥有 Create DB 的能力。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

需要注意:

  1. 语句要以分号结尾
  2. 密码要用单引号括起来

数据库转让

紧接着我们把刚刚创建的数据库 database_developmentowner 赋予给 testuser。这样 testuser 就拥有了该数据库的操作权限了。

ALTER DATABASE database_development OWNER TO testuser;

我们输入 \l 查看数据库列表,可以看到 database_development 的 owner 已经变成了 testuser

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

最后,我们 \q 退出连接 再重新连接一下,输入如下命令,回车!再输入密码 12345678,回车!成功连接!

psql database_development -U testuser -W

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

设置安全策略

但其实,你会发现,即使不输入密码或者输错密码,也能登入成功。这里我们不卖关子,是因为 PostgreSQL 默认策略 trust 本地数据库连接免登陆配置导致的。

我们找到 PostgreSQL 安装的位置,查看 pg_hba.conf 就能看到相应的用户安全策略配置。

cat /usr/local/var/postgresql@15/pg_hba.conf

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

所以在生产环境,大家一定要配置好合适的 PostgreSQL 访问安全策略,具体认证方式参考 21.5. Password Authentication

这里我们可以参考以下配置按需设置。

# TYPE  DATABASE       USER       ADDRESS        METHOD
# ********* 服务端直连本地 ********
# 超级用户:免密登录
local   all            flcwl                     trust
# 其它用户:密码验证登录
local   all            flcwl                     md5

# ********* 网络登录 ******** 
# 超级用户:拒绝从网络登录
host    all            flcwl      0.0.0.0/0      reject
# 其它用户:密码验证登陆
host    all            all        0.0.0.0/0      scram-sha-256
# 流复制用户:密码验证登录
host    replication    all                       md5

最后我们保存,重新加载安全策略配置使其生效。

pg_ctl reload -D /usr/local/var/postgresql@15

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

我们再重新连接下数据库,你会发现密码必须输入正确才能连接成功。大功告成!

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

常用命令(附录)

这里简单罗列了下常用的命令,方便大家更好的使用。

全局命令

以下是在终端下,常用的全局可执行命令。

  • 创建数据库
createdb database_development
  • 连接数据库
psql database_development -h hosthost -U testuser -W
  • 删除数据库
dropdb database_development

数据库内命令

以下是在数据库连接时,常用的一些命令。

  • 查看此次连接信息(包括登录用户名、连接端口号)。
\conninfo
  • 退出连接
\q
  • 查询用户列表
\du
  • 查询数据库列表
\l
  • 切换当前连接的登录用户
\c - other_user
  • 切换当前连接的数据库
\c - other_database

小结

本小结带大家完整介绍了 PostgreSQL 从安装到用户认证连接数据库完整过程。其中,有很多细节不做深入,感兴趣的同学可以继续探索。


Prisma 准备

接下来,我们开始使用 ORM 来连接访问我们的数据库。前面已经介绍了 ORM 技术选型,最终我们选择使用 Prisma

安装 Prisma

首先是安装。回到之前我们初始化的 Midway HelloWorld 项目,在项目根目录下执行:

npm i prisma @prisma/client

初始化配置

之后我们执行 npx prisma init 初始化 prisma 配置。

执行后会生成 2 个文件:

  • .env 文件:用于 dotenv 环境变量配置,先暂时忽略
  • schema.prisma 文件:表示 Prisma 配置文件,定义了数据源、生成器以及数据模型

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

其中配置项定义如下:

  • datasource 表示数据库连接的是数据库适配器、以及数据库连接地址。

  • generator 指定了等会要生成的 Prisma Client 的语言为 JavaScript。

schema.prisma 文件中可以看到,默认数据库配置的就是 postgresql。所以,我们只需要替换建立连接的 url 即可,具体如何配置参考如下。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

按照上节 PostgreSQL 示例,我们的数据库源 url 最终会是这个样子:

url = "postgresql://testuser:123456789@localhost:5432/database_development"

创建第一个数据模型

初始化完成之后,我们再来尝试创建一个最简单的 User 数据模型,作为我们的第一张数据库表 users

// schema.prisma
generator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
+  url      = "postgresql://testuser:12345678@localhost:5432/database_development"
}

+ // 用户表
+ model User {
+   id       String  @id @default(cuid())
+   username String  @unique
+   password String
+   salt     String
+   email    String? @unique

+   createdAt DateTime @default(now()) @map("created_at")
+   updatedAt DateTime @updatedAt @map("updated_at")
+   deletedAt DateTime? @map("deleted_at")
+   deleted   Boolean  @default(false)

+   @@map("users")
+ }

关于用户表的模型配置,已经非常语义化了,这里不做过多解释,具体参考官方文档说明

执行第一次数据库变更

万配俱配,我们执行脚手架 migrate dev 命令进行迁移:因为数据库中其实并没有 users 表,那么最终会自动创建该表。

npx prisma migrate dev --name init

--name init 就是给这次迁移起个名字,方便后续查阅和维护。比如这里就叫 init

执行完成之后,你会看到会生成一个迁移 sql 文件日志,里面表示本次迁移时底层数据库具体执行的 sql 语句,用于跟踪数据库变更

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

该命令实际会做三件事:

  1. 保存迁移:Prisma 将生成本次迁移时底层数据库具体需要执行的 SQL 语句,用于跟踪数据库变更。SQL 日志文件会保存到 prisma/migrations 文件夹内,可以跟随代码提交到 Git 远端。
  2. 执行迁移:Prisma 将执行迁移文件中的 SQL 命令,完成底层数据库中的操作,这里就是创建 users 表。
  3. 生成 Prisma Client:Prisma 将会基于最新的 schema.prisma 配置 生成用于 Prisma Client 查询的 API 和相关数据模型的 TS 安全类型。

使用 Prisma Studio 可视化查看

我们在项目根目录下运行以下命令打开 Prisma Studio,这样我们可以可视化查看和编辑数据库中的数据。

npx prisma studio

该命令会启动一个本地服务,浏览器访问 http://localhost:5555 可以看到刚刚创建的 users 表。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

目前表已经创建有了,但是里面还没有任何数据,我们可以可视化操作一波:在 users 表中添加一条数据。

  1. 点击 Add record 按钮

  2. 输入必填字段值 我们只需要输入 usernamepasswordsalt 字段下输入内容即可(这里用于演示统一输入 Flcwl)。其它字段要么是自动生成,要么是可选非必填,我们直接忽视。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

  1. 点击 Save 1 change 按钮

此时,表中已经出现了一条数据(record),说明我们数据库写入数据成功了。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

小结

本小结主要初始化 Prisma 并打通了底层数据库 PostgreSQL。

同时,通过 Prisma Studio 可以可视化查看数据库中的数据,以及完成对数据的可视化 CRUD 操作。

目前使用下来,你有没有感觉到 Prisma 还是很香的~


实战数据库查询

接下来,我们得进入到实战代码环节,主要使用 Prisma Client API 来访问数据库。

Prisma Client 会自动生成基于模型的安全的数据类型及其数据库 API,这样我们就可以利用 TS 提供的自动补全功能来提升开发体验。

创建 PrismaClient 实例

我们在 src 目录下创建一个文件 prisma.ts,用来初始化 Prisma Client 实例。

// src/prisma.ts

import { PrismaClient } from '@prisma/client';

export const prisma = new PrismaClient();

PrismaClient 实例中包含许多实用的 API,大家可以使用它快速完成 CRUD:

  • findUnique
  • findFirst
  • findMany
  • create
  • update
  • upsert
  • delete
  • createMany
  • updateMany
  • deleteMany
  • count
  • aggregate
  • groupBy

重构 UserService

MidwayJS 全栈开发(二)HelloWorld实战UserService 根据 uid 查询用户信息,我们当时是写死 Mock 数据的。这里我们使用 findFirst API 进行重构,实现真正的数据库访问查询。

// src/modules/user/user.service.ts

import { Provide } from '@midwayjs/decorator';
+ import { prisma } from '../../prisma';

@Provide()
export class UserService {
  async get(uid: string) {
    if (!uid) return null;

-   // mock 数据库查询返回数据
-   return {
-     uid: uid,
-     username: '不败花',
-     phone: '12345678901',
-     email: 'xxxxxx@xxx.com',
-   };

+   return prisma.user.findFirst({
+     // deleted: false 表示查询的用户未被删除
+     where: { id: uid, deleted: false },
+     // 过滤掉 password 等敏感字段数据返回
+     select: {
+       id: true,
+       username: true,
+       email: true,
+       createdAt: true,
+       updatedAt: true,
+     },
+   });
+ }
}

因为我们前面有解释,执行了 prisma migrate 命令会生成相关的模型 TS 类型,所以 prisma.user 是有安全的类型提示的哦。

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

再之后,别忘了我们还要执行 npm run dev 启动我们的 Midway 服务。

模拟请求测试

服务启动成功后,我们简单模拟一下请求发送:请求入参为 uid

MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI

最终返回 usernameFlcwl,对照 Prisma Studio 数据符合预期,完美!

小结

本小结主要从代码层面使用 Prisma Client 工具访问 PostgreSQL 数据库中的数据,流程基本打通。

PS:对MidwayJS 全栈开发(二)HelloWorld实战 不太熟悉的同学可以回过头再回顾一下。

全文总结

本篇主要是实战,完整串联了 Prisma 和 PostgreSQL 实现 CRUD 的流程。

目前只是简单入门,Prisma 号称最先进的 ORM,其中包含三个部分,需要掌握:

  • Prisma Client: 自动生成、类型安全的查询构建器
  • Prisma Migrate: 自动化数据库迁移工具
  • Prisma Studio: 查询和编辑数据库模型数据的可视化界面

而 PostgreSQL 号称最强大的开源数据库系统,涉及到 SQL 技术,需要学习的东西还有很多,这里也是浅尝辄止。

对以上两者,感兴趣的同学可以继续深入探索学习,相信在未来工作中一定有用武之地。