準備
データベース
DockerにPostgresqlコンテナーを作成する
Dockerでも何でも接続できる環境さえあれば良い、ここではDockerを利用します。コンテナーやボリュームなどのみ削除することでパソコンも綺麗になるるクラウドを使った場合の後クリアなど気にしない。
version: '3.8'
services:
postgres:
image: postgres:15
container_name: postgres_svr
environment:
POSTGRES_DB: exampledb # PostgreSQLデータベース名
POSTGRES_USER: exampleuser # PostgreSQLユーザー名
POSTGRES_PASSWORD: examplepass # PostgreSQLユーザーパスワード
ports:
- "5432:5432" # ホスト:コンテナ (PostgreSQL)
volumes:
- type: bind
source: /Users/twonine/Docker/dbsvr/postgre
target: /var/lib/postgresql/data
restart: always
各種バージョン
nodejs: 18.20.2
nestjs: 10.0.0
prisma: 5.22.0
npm: 10.5.0
postgresql: 15
前提
プロジェクトの生成はできた状態からする。簡単に使用コマンドを列挙しておきます。
作成APIのテストはPostmanを利用する。
$ nest new app-name
// npm, typescript, jestを選択
$ cd app-name
$ nest g mo user [--no-spec]
$ nest g co user [--no-spec]
$ nest g service user [--no-spec]
初め
フォルダーとファイルの構成
$ tree -I 'node_modules|dist'
.
├── README.md
├── nest-cli.json
├── package-lock.json
├── package.json
├── prisma
│ ├── migrations
│ │ ├── 20241116011831_init
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ └── schema.prisma
├── src
│ ├── app.controller.spec.ts
│ ├── app.controller.ts
│ ├── app.module.ts
│ ├── app.service.ts
│ └── main.ts
├── test
│ ├── app.e2e-spec.ts
│ └── jest-e2e.json
├── tsconfig.build.json
└── tsconfig.json
Prisma導入
パッケージインストール
$ npm install prisma --save-dev
$ npm install @prisma/client
Prisma初期化
$ npx prisma init
$ tree -I 'node_modules|dist'
.
├── prisma
│ └── schema.prisma
├── src
.
$ cat .env
# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
DATABASE_URL="postgresql://johndoe:randompassword@localhost:5432/mydb?schema=public"
$
Modelを複数ファイルにしたい
Prisma公式では単一ファイルの支援するとしていますがいくつかの方法があるようで一旦関連Linkを共有したいと思います。
Prisma \docs\Tips for multi-file Prisma Schema
Prisma-import
接続文字列設定
Dockerの設定を参考にして接続文字列を更新する。
DATABASE_URL="postgresql://examplduser:examplepass@localhost:5432/exampledb?schema=public"
テーブルのスキマー作成
“npx prisma init”で生成されたschema.prismaにuserテーブル用のmodelを作成、フィルードについての細かい説明は省略します。<Prisma/docs/Models>
model User {
id Int @default(autoincrement()) @id
email String @unique
name String?
created_at DateTime @default(now())
updated_at DateTime @default(now())
deleted_at DateTime?
}
テーブルの生成
$ npx prisma migrate dev --name init
Environment variables loaded from .env
Prisma schema loaded from prisma/schema.prisma
Datasource "db": PostgreSQL database "exampledb", schema "public" at "localhost:5432"
Applying migration `[yyyymmddhhmmdd]_init`
The following migration(s) have been created and applied from new schema changes:
migrations/
└─ [yyyymmddhhmmdd]_init/
└─ migration.sql
Your database is now in sync with your schema.
✔ Generated Prisma Client (v5.22.0) to ./node_modules/@prisma/client in 34ms
$
migrations/[yyyymmddhhmmdd]_init/migration.sqlが生成されDDLが出来ます。
スキマーフォルダー変更
「prisma init」からできる「prisma」変更は不可
「migration」作業時に参照するschema.prismaのフォルダーはpackage.jsonで変更可能、フォルダー名をDB名や環境名などで区別することも良いかもしれません。
$ cat package.json
...
"prisma": {
"schema": "./my-db/schema.prisma"
}
...
$ npx prisma migrate dev --name init
...
$ tree -I 'node_modules|dist'
├── my-db
│ ├── migrations
│ │ ├── [yyyymmddhhmmss]_init
│ │ │ └── migration.sql
│ │ └── migration_lock.toml
│ └── schema.prisma
├── prisma
$
アプリケーションから接続
DB接続Serviceを作成
src/database $ touch prisma.service.ts
src/database $ vi prisma.service.ts
import { Injectable, OnModuleInit } from "@nestjs/common";
import { PrismaClient } from "@prisma/client";
@Injectable()
export class PrismaService extends PrismaClient implements OnModuleInit {
async onModuleInit() {
try {
await this.$connect();
} catch(err) {
console.error(err);
throw new Error("Method not implemented.");
}
}
}
開発では良いと思いますが、productionではConnection Poolを顧慮するべきかと思います。
Prisma/docs Connection Pooling
CRUDの作成
repositoryを作成することもありますがここではuser.service.tsで作成します。<prisma/docs/CRUD>
import { Injectable } from '@nestjs/common';
import { CreateUserDto, UpdateUserDto } from './user.dto';
import { PrismaService } from 'src/database/prisma.service';
import { User, Prisma } from '@prisma/client';
@Injectable()
export class UserService {
constructor(private readonly prismaService: PrismaService) {}
...
...
}
Create
...
async create(createUserDto: CreateUserDto): Promise<User>{
const inputData: Prisma.UserCreateInput = {
email: createUserDto.email,
name: createUserDto?.name || undefined
};
return this.prismaService.user.create({ data: inputData });
}
...
Read
...
async findAll() {
const res = await this.prismaService.user.findMany();
return res;
}
async findOne(id: number) {
const where: Prisma.UserWhereUniqueInput = { id };
const res = await this.prismaService.user.findUnique({
where
});
return res;
}
...
Update and Delete
...
async update(id: number, updateUserDto: UpdateUserDto) {
const where: Prisma.UserWhereUniqueInput = { id };
const inputData: Prisma.UserCreateInput = {
email: updateUserDto?.email || undefined,
name: updateUserDto?.name || undefined
};
const res = await this.prismaService.user.update({
where: where,
data: inputData,
})
return res;
}
async delete(id: number) {
const where: Prisma.UserWhereUniqueInput = { id };
const res = await this.prismaService.user.delete({
where
});
return res;
}
...
公式ページなど
Prisma ドキュメンテーション
Prisma CRUD
Docker compose