在Nodejs项目的ORM中,Prisma热度越来越高,如果数据库使Postgresql, Mysql等关系型数据库,还是非常建议使用的。Mongo数据库的的有些特性不支持,建议还是使用typegoose或者mongoose.
下面说一下在Nestjs中prisma的使用、打包、部署。
Nestjs项目中引入prisma
假设当前已经有nestjs项目,需要添加Prisma ORM, 参考以上官方文档,执行如下操作
bash
yarn add prisma -D
执行成功后,会在项目根目录下生成prisma目录和.env文件,在这里,我期望prisma的目录放到src目录下,因此在package.json中添加以下配置
json
"prisma": {
"schema": "src/db/postgresql/schema.prisma"
}
按配置中的路径创建相关目录,并把schma.prisma文件移动到目标目录
bash
mkdir -p src/db/postgresql
mv prisma/schema.prisma src/db/postgresql
rm -rf prisma
修改.env中的数据库连接地址
ini
DATABASE_URL="postgresql://test:123456@192.168.3.31:5432/prisma-example?schema=public"
添加数据库模型定义
kotlin
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
// Looking for ways to speed up your queries, or scale easily with your serverless or edge functions?
// Try Prisma Accelerate: https://pris.ly/cli/accelerate-init
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id Int @id @default(autoincrement())
name String
email String
posts Post[]
comments Comment[]
}
model Post {
id Int @id @default(autoincrement())
title String
content String
published Boolean
authorId Int
author User @relation(fields: [authorId], references: [id])
comments Comment[]
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model Comment {
id Int @id @default(autoincrement())
postId Int
post Post @relation(fields: [postId], references: [id])
userId Int
user User @relation(fields: [userId], references: [id])
content String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
安装prisma client
bash
yarn add @prisma/client
# 生成prisma js client
yarn prisma generate
执行完yarn prisma generate
命令后,会在node_nodules目录下生成.prisma/client目录, 该目录中的内容正是根据前边定义的schema.prisma文件动态生成。当前也可以通过配置,生成到node_nodules之外的目录下面。
例如, 修改schema.prisam文件,指定生成的目标目录,注意,该目标目录的路径是相对schema.prisma文件的路径。
ini
generator client {
provider = "prisma-client-js"
output = ".prisma/client"
}
这里我使用默认生成路径,不添加output配置。
使用定义的数据库模型初始化数据库
❕ 注意,执行以下命令,DATABASE_URL中配置的连接账号必须要有创建数据库的权限。
通常,该命令都是在本地开发环境,连接本地数据库去执行,并不会直接连接部署环境执行。
bash
yarn prisma migrate dev --name init
以上命令执行完成以后,会有如下影响
- 生成了迁移脚本
在 src\db\postgresql
目录下,生成了migrations目录,里边包含了将要在数据库执行的脚本文件migration.sql
- 在目标数据库中创建了数据库表
查看数据库,会发现user, post, comment表已经创建出来
- 在数据库中记录了migration脚本的执行历史记录
细心的同学会发现,prisma-example数据库中额外生成了_prisma_migrations
, 这张表的作用正是记录脚本执行历史。查看一下表的内容:
连接数据库
- 添加nestjs-prisam模块
bash
yarn add nestjs-prisma
- app.module文件中引入prisma module
typescript
@Module({
imports: [PrismaModule.forRoot()],
controllers: [AppController],
providers: [AppService],
})
export class AppModule {}
- 添加创建用户、查询用户接口
实现业务逻辑
typescript
export class AppService {
constructor(private readonly _prisma: PrismaService) {}
async createUser() {
const user = await this._prisma.user.create({
data: {
name: 'John Doe',
email: 'john.doe@example.com',
},
});
return user;
}
async findUser(id: number) {
return this._prisma.user.findUnique({
where: {
id,
},
});
}
}
添加访问路由
typescript
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Post('user)
createUser() {
return this.appService.createUser();
}
@Get('user')
findUser(@Query('id') id: string) {
return this.appService.findUser(Number(id));
}
}
- 启动服务
bash
yarn start:dev
- 请求创建用户接口
服务构建
- 添加.dockerignore文件
bash
# docker镜像构建,需要排除的文件及目录
/node_modules
/dist
- 创建Dockerfile
Dockerfile
FROM node:18.14-slim as builder
LABEL Author="mobiusy"
WORKDIR /build
RUN yarn config set registry https://registry.npmmirror.com
COPY package.json ./package.json
COPY yarn.lock ./yarn.lock
RUN yarn
COPY ./ ./
RUN yarn prisma generate && yarn build
FROM node:18.14-slim as prod
LABEL Author="mobiusy"
# 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
WORKDIR /opt/application
# 将生成的可执行文件copy到当前工作目录下
COPY --from=builder /build/dist ./dist
COPY --from=builder /build/node_modules ./node_modules
COPY --from=builder /build/package.json ./package.json
# 容器启动时执行的命令
CMD ["yarn", "start:prod"]
- 添加docker-compose.yaml文件
yaml
version: '3.7'
services:
wdp5-backend:
image: "prisma-example:v0.0.1"
build:
context: ./
dockerfile: Dockerfile
container_name: prisma-example
restart: always
env_file:
- ./.env
ports:
- 33100:13000
- 构建并启动容器
css
docker-compose up -d --build
- 测试接口
使用pkg构建二进制文件并docker部署
- 安装pkg
csharp
yarn add pkg -D
- 修改pakcage.json文件,增加打包配置
json
"bin": "dist/main.js",
"pkg": {
"targets": [
"node18"
],
"assets": [
"node_modules/.prisma/**/*"
],
"output": "nestjs-prisma-example"
}
- 新增pkg.Dockerfile
Dockerfile
FROM node:18.14-slim as builder
LABEL Author="mobiusy"
WORKDIR /build
RUN yarn config set registry https://registry.npmmirror.com
COPY package.json ./package.json
COPY yarn.lock ./yarn.lock
RUN yarn
COPY ./ ./
RUN yarn prisma generate && yarn build
RUN yarn pkg package.json
FROM node:18.14-slim as prod
LABEL Author="mobiusy"
# 设置时区
RUN ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
WORKDIR /opt/application
# 将生成的可执行文件copy到当前工作目录下
COPY --from=builder /build/nestjs-prisma-example ./
# 容器启动时执行的命令t
CMD ["./nestjs-prisma-example"]
- docker-compose.yaml中新增service
yaml
version: '3.7'
services:
wdp5-backend:
...
# 以下为新增内容
wdp5-backend-pkg:
image: "prisma-example:v0.0.1-pkg"
build:
context: ./
dockerfile: pkg.Dockerfile
container_name: prisma-example-pkg
restart: always
env_file:
- ./.env
ports:
- 33200:13000
- 构建并启动容器
css
docker-compose up -d --build
⚠️ 这一步会使用pkg打包linux可执行二进制文件,pkg在打包过程中会下载依赖,如果下载出错,请使用科学上网打包,或预下载依赖放到打包环境中, 具体细节这里不展开说了。
- 接口测试
结语
这一篇文章讲了nestjs中Prisma ORM的安装,使用,以及源码部署和二级制部署的方式。
对于Prisma的使用,有很多细节的地方,特别是Prisma Cli,建议仔细阅读官方文档。
下一篇文章里,我会讲一下如何使用Prisma提供的增量脚本功能,以及如何在生产环境中,去保持数据库和服务的一致性。