MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI
MidwayJS 全栈开发(五)Prisma 与 PostgreSQL 实战 RestAPI
前言
上一篇内容回顾:# MidwayJS 全栈开发(四)ORM 技术选型 。
前面铺垫了很多技术介绍,终于,在本篇我们进入到实战环节:通过 Prisma 和 PostgreSQL 实现 CRUD 打造 RestAPI。
PostgreSQL 准备
对于数据库管理系统,作为全栈的我们选择使用 PostgreSQL。
安装 PostgreSQL
首先是安装,大家可以在本地按照网上的教程操作下。(安装教程不做详述,推荐使用 brew install postgresql@15
安装最新版 15.2
。)
image.png
安装完成后,记得按提示将环境变量配置好。这里我们可以输入 psql --version
验证环境配置是否 OK。
image.png
启动 PostgreSQL
我们可以输入 brew services start postgresql@15
启动本地的 PostgreSQL 服务。
image.png
另外,我们可以输入 brew services list
查看 PostgreSQL 的服务状态,确保它处在 started
即表示运行中的状态。
image.png
服务运行OK,但是在使用数据库之前,我们需要创建一个数据库,这样才能在里面创建表,完成增删改查。
创建数据库
我们可以在终端通过全局命令 createdb
创建数据库,库名为 database_development
,作为本地开发调试数据库。
createdb database_development
恭喜没有任何提示或报错,那说明执行成功。
接着我们输入 psql database_development
登入进 database_development
数据库。 登入后提示符变成 database_development=#
。
image.png
Q:大家或许很奇怪,连接数据库难道不需要用户和密码认证吗?数据库的安全性怎么保证呢?
其实不是的。 我们可以在里面输入 \conninfo
查看此次连接信息。
image.png
可以看到,我们是作为用户(flcwl
)登录进来的,默认端口 5432
。其实 PostgreSQL 默认会把当前登录电脑系统的账户名称(flcwl
)会作为 superuser
(超级管理员) 角色创建用户,作为预设,本机无需密码认证。
这里,我们可以输入 \du
查看现有的用户角色及其权限信息,得以验证。
image.png
那么我们前面创建数据库,连接数据库的这些操作,其实都是基于 superuser
角色进行的,自然可以一气呵成地操作成功了。
创建用户
从上面可以看到超级管理员 superuser
的权限非常之大,为了安全起见,在实际业务场景中,我们会创建和使用其它用户角色(遵循最小权限原则)连接和操作数据库。
首先我们创建一个用户: - 用户名就叫 testuser
,密码为 12345678
; - 并赋予创建数据库的权限 CREATEDB
,方便后续 Prisma ORM 使用;
CREATE USER testuser WITH PASSWORD '12345678';
ALTER ROLE testuser CREATEDB;
可以看到,testuser
用户创建成功了,并且拥有 Create DB
的能力。
image.png
需要注意: 1. 语句要以分号结尾 2. 密码要用单引号括起来
数据库转让
紧接着我们把刚刚创建的数据库 database_development
的 owner
赋予给 testuser
。这样 testuser
就拥有了该数据库的操作权限了。
ALTER DATABASE database_development OWNER TO testuser;
我们输入 \l
查看数据库列表,可以看到 database_development
的 owner 已经变成了 testuser
。
image.png
最后,我们 \q
退出连接 再重新连接一下,输入如下命令,回车!再输入密码 12345678
,回车!成功连接!
psql database_development -U testuser -W
image.png
设置安全策略
但其实,你会发现,即使不输入密码或者输错密码,也能登入成功。这里我们不卖关子,是因为 PostgreSQL 默认策略 trust 本地数据库连接免登陆配置导致的。
我们找到 PostgreSQL 安装的位置,查看 pg_hba.conf
就能看到相应的用户安全策略配置。
cat /usr/local/var/postgresql@15/pg_hba.conf
image.png
所以在生产环境,大家一定要配置好合适的 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
image.png
我们再重新连接下数据库,你会发现密码必须输入正确才能连接成功。大功告成!
image.png
常用命令(附录)
这里简单罗列了下常用的命令,方便大家更好的使用。
全局命令
以下是在终端下,常用的全局可执行命令。
- 创建数据库
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 配置文件,定义了数据源、生成器以及数据模型
image.png
其中配置项定义如下:
datasource
表示数据库连接的是数据库适配器、以及数据库连接地址。generator
指定了等会要生成的 Prisma Client 的语言为 JavaScript。
在 schema.prisma
文件中可以看到,默认数据库配置的就是 postgresql
。所以,我们只需要替换建立连接的 url
即可,具体如何配置参考如下。
image.png
按照上节 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 语句,用于跟踪数据库变更,
image.png
该命令实际会做三件事: 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
表。
image.png
目前表已经创建有了,但是里面还没有任何数据,我们可以可视化操作一波:在 users 表中添加一条数据。
- 点击
Add record
按钮 - 输入必填字段值 我们只需要输入
username
、password
、salt
字段下输入内容即可(这里用于演示统一输入Flcwl
)。其它字段要么是自动生成,要么是可选非必填,我们直接忽视。
image.png
- 点击
Save 1 change
按钮
此时,表中已经出现了一条数据(record),说明我们数据库写入数据成功了。
image.png
小结
本小结主要初始化 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
是有安全的类型提示的哦。
image.png
再之后,别忘了我们还要执行 npm run dev
启动我们的 Midway 服务。
模拟请求测试
服务启动成功后,我们简单模拟一下请求发送:请求入参为 uid
。
image.png
最终返回 username
为 Flcwl
,对照 Prisma Studio 数据符合预期,完美!
小结
本小结主要从代码层面使用 Prisma Client 工具访问 PostgreSQL 数据库中的数据,流程基本打通。
PS:对MidwayJS 全栈开发(二)HelloWorld实战 不太熟悉的同学可以回过头再回顾一下。
全文总结
本篇主要是实战,完整串联了 Prisma 和 PostgreSQL 实现 CRUD 的流程。
目前只是简单入门,Prisma 号称最先进的 ORM,其中包含三个部分,需要掌握: - Prisma Client: 自动生成、类型安全的查询构建器 - Prisma Migrate: 自动化数据库迁移工具 - Prisma Studio: 查询和编辑数据库模型数据的可视化界面
而 PostgreSQL 号称最强大的开源数据库系统,涉及到 SQL 技术,需要学习的东西还有很多,这里也是浅尝辄止。
对以上两者,感兴趣的同学可以继续深入探索学习,相信在未来工作中一定有用武之地。