ファランクスブログ

© 2026 all rights reserved.
  1. blog
  2. prisma
  • インストール・概要
  • Prisma v7
  • DBスキーマ
  • スクリプトコマンド
  • データが無い場合
  • migrateの使用
  • .gitignore
  • 開発/本番でDBを分ける
  • migrateを途中から取り入れる場合
  • Vercel
  • Prisma Clientの生成
  • connection_limit
  • The database server was reached but timed out
  • モデル
  • モデルの型を使用
  • リレーションも含めた型
  • モデルの内容
  • idは自動生成

Prisma:(1)

2026年6月21日

https://www.prisma.io/docs/orm/getting-started

インストール・概要

pnpm add prisma tsx @types/pg --save-dev
pnpm add @prisma/client @prisma/adapter-pg dotenv pg
pnpm add -D dotenv-cli
  • npx prisma initコマンドでルートにprismaフォルダとconfigファイルができる。

pull と migrate / push:

  • pull:DBの構造を元にSchemaを作成

  • migrate / push:Schemaを元にDBを変更

    • migrateはsqlファイルとして履歴が残る / pushは残らない

Prisma v7

prisma.ts :

import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "./generated/prisma";

const adapter = new PrismaPg({
  connectionString: process.env.VERCEL_DATABASE_URL,
},{ schema: "" });

const globalForPrisma = global as unknown as {
  prisma: PrismaClient;
};

export const prisma =
  globalForPrisma.prisma ||
  new PrismaClient({
    adapter,
  });

if (process.env.NODE_ENV !== "production") globalForPrisma.prisma = prisma;

DBスキーマ

~v7までは環境変数にDBのスキーマを含めた接続URLを書くだけで良かったが、v7では接続URLを書くだけだとpulbicスキーマの構造が取得される。

対策1(推奨): prisma.ts

const adapter = new PrismaPg(
  {
    connectionString: process.env.DATABASE_URL,
  },
  {
    schema: "", // 追加
  }
);

対策2: schema.prisma

generator client {
  provider = "prisma-client"
  output   = "./generated/prisma"
}

datasource db {
  provider = "postgresql"
  schemas  = ["scheme_name"]
}

model User {
  ...
  @@schema("scheme_name")
}
  • @@schema("")をすべてのモデルに書く。

スクリプトコマンド

Prismaは.env しか自動で読み込まないのでdotenv-cliを用いたスクリプトコマンドを予め登録する。

  "scripts": {
    "db:pull": "dotenv -e .env.development.local -- npx prisma db pull",
    "db:generate": "dotenv -e .env.development.local -- npx prisma generate",
    "db:push": "dotenv -e .env.development.local -- npx prisma db push",
    "db:studio": "dotenv -e .env.development -- npx prisma studio"
    "db:migrate": "dotenv -e .env.development -- npx prisma migrate dev"
  },
  • migrateのやり方に慣れたらdb:pushは削除した方が良い。

データが無い場合

import { prisma } from "@/prisma/prisma";

export const getTags = async () => {
  try {
    return await prisma.tag.findMany();
  } catch (error) {
    console.error("Failed to fetch tags:", error);
    return [];
  }
};
  • データ(レコード)が空の場合、空配列が返るので明示的に空配列を返す必要は無い。

  • 上記はcatchで明示的に空配列を返しているが、DB接続やクエリ失敗時でもアプリを安全に動かすため

migrateの使用

*pull/pushコマンドで管理している既存のDBに対してmigrateコマンドを実行するとデータを全削除することが促される。Yキーを押した時点でDB ( schema )からデータがすべて削除される。

migrateについて:

  • migrate devでprisma.schemaのモデルをもとにDBにテーブルが作られる。DBスキーマを事前に作成する必要はない。

  • migrate devの実行時に変更履歴がsqlファイルとして残る。また_prisma_migrationsというmigrationの管理用テーブルがDBに作成される。

  • *スクラッチの状態からmigrateコマンドでDBを管理しないと難しい仕組みになっているので、場合によってはpush/pullコマンドで管理する方に割り切った方が良い。

.gitignore

重要:

  • prisma/migrationsフォルダをgitignoreに含めてはいけない。prisma/generatedはスキーマがあれば生成できるので含めていい。

  • migrationsフォルダがローカルにないとmigrateコマンド時にエラーになる。

    • *本番DBからローカルにmigrationsフォルダを生成するコマンドは無い。

開発/本番でDBを分ける

docker-compose.yml:

services:
  db:
    image: postgres:16
    container_name: dev_db
    ports:
      - "5432:5432"
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: pass
      POSTGRES_DB: dev_db
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
  • 開発時はdocker compose up -dでコンテナのPostgresを使う。

.env.local:

DATABASE_URL="postgresql://user:pass@localhost:5432/dev_db?schema=test"

package.json:scripts

"vercel-build": "prisma generate && prisma migrate deploy && next build"
  • Vercelダッシュボードのビルドコマンドを上記に変更

migrateを途中から取り入れる場合

pull/push で管理しているPrismaを使ったアプリをmigrateによる管理に切り替える場合

  1. 既存データがあるDBの接続URLの状態でdb pull をしてprisma.schemaにモデルを作成

  2. 空フォルダ /prisma/migrations/0_initを作成

  3. 以下のコマンドを実行

npx dotenv -q -e .env.development -- npx prisma migrate diff \
--from-empty \
--to-schema prisma/schema.prisma \
--script > prisma/migrations/0_init/migration.sql
  1. 「3」で/migrations/0_initに作成された migration.sqlの上部に以下のような行がある場合は削除

[dotenv@17.2.3] injecting env (0) from .env.development -- tip: ✅ audit secrets and track compliance: https://dotenvx.com/ops
  1. 以下のコマンドを実行

npx dotenv -q -e .env.development -- npx prisma migrate resolve --applied 0_init
  • *事前に色々いじっていて本番DBに_prisma_migrationsテーブルがある場合は慎重に削除する。

  1. DBの接続URLを開発のもの(コンテナ)に切り替えてからmigrateコマンドを実行

pnpm run db:migrate
  • *コンテナのDB(スキーマ)に_prisma_migrationsテーブルがあるとエラーになるのでテーブルを削除するか、スキーマ自体を削除してからコマンドを再実行

  1. リポジトリにgit pushをして Vercelで migrate deployコマンドが成功するか確認

以降:

  • 開発環境でschema.prismaに変更を行ったらmigrate devでmigrationファイルを作成する

Vercel(migrate deploy)でエラーが出るケース:

  • モデルのidのStringをIntに変えたような場合、DBには既にStringのidとしてデータがあるのでエラーが出る。

    • 対策はモデルを変えたテーブルのデータを全て消す

  • モデル名(テーブル名)自体の変更も既存の構造に変更を加える事を意味するので対策が難しい

Vercel

Prisma Clientの生成

Prismaを使ったNextjsアプリをそのままVercelにデプロイするとエラーになる

原因:

  • Prisma Clientはschema.prismaを元に生成されるコードを必要とするが、Vercelのビルドコマンドはnext build だけなので、ビルド時にPrisma Client が未生成になりエラーが出る

対策 1(推奨):Vercelの build command を以下にoverride

  • npx prisma generate && turbo run build

対策2:

  • package.jsonの scripts に以下を追加

  "scripts": {
    "postinstall": "npx prisma generate"
  },
  • ターミナルで依存関係をインストールする度にpostinstallが走る

connection_limit

Timed out fetching a new connection from the connection pool. More info: http://pris.ly/d/connection-pool (Current connection pool timeout: 10, connection limit: 3)

原因:

  • ビルド時に静的ページのプリレンダリングを行う際に並行処理で同時にPrismaへの接続が行われるので、すぐにデフォルトのconnection_limit = 3 に達した為

対策:

  • 環境変数のDATABASE_URLの後ろに以下を追加するとビルドエラーがなくなった

&connection_limit=5

The database server was reached but timed out

migrateコマンドを取り入れてから発生。原因はわからないが以下でこのエラーは消える

対策:

  • Vercelのダッシュボードから環境変数に以下を追加

PRISMA_SCHEMA_DISABLE_ADVISORY_LOCK=true

モデル

モデルの型を使用

schema.prismaのモデルはPrisma Clientを生成するとgeneratedフォルダ内に型情報として残るので、それを型として使うことができる。

import { User } from "@/prisma/generated/prisma";

const exampleUser: User = {
  id: "asd",
  name: "rwe",
  age: 11,
};

リレーションも含めた型

Prisma.GetPayload:

import { Prisma } from "@/prisma/generated/prisma";

type Props = Prisma.ItemsGetPayload<{
  include: { categories: { include: { category: true } } };
}>[];

typeof(推奨):

const items = await prisma.Item.findMany({
  include: {
    tags: true,
  },
})

export type Item = (typeof items)[number]

モデルの内容

@map:

  userId             String  @map("user_id")
  • DBではuser_idだが、補完ではuserIdとして使える

@@map:

model Post {
  ...
  @@map("post")
}
  • DBのテーブル名はpost、型としてはPostで使える

アプリはcamelCase、DBはsnake_caseが一般的なので @mapや@@mapの設定を見ることが多い。モデルが大文字スタートなのは型の慣習に合わせるため。慣習に従うならモデル名は大文字スタートのcamelCase、要素は小文字スタートのcamelCaseで書いて@mapでsnake_caseに、テーブルは@@mapでsnake_caseにする。

@relation:

 model User {
  id    Int    @id @default(autoincrement()) // Postの参照先
  name  String

  posts Post[]
}

model Post {
  id      Int    @id @default(autoincrement())
  title   String
  content String

  authorId Int     // 外部キー
  author   User    @relation(fields: [authorId], references: [id])
}
  • PostがどのUserのものかを示す情報 (= 外部キー)はPostが持つ

  • 1対多の関係では「多」の方が外部キーを持つ

  • ( fields: [外部キー] , references: [外部キーが参照する先] )

Cascade:

model Recipe {
  id                  Int                   @id @default(autoincrement())
  dishName            String
  ingredient          Ingredient[]
  createdAt           DateTime              @default(now())
}

model Ingredient {
  id       Int    @id @default(autoincrement())
  name     String
  recipeId Int
  recipe   Recipe @relation(fields: [recipeId], references: [id], onDelete: Cascade)
}
  • 参照先 = 親(Recipe)が削除されたら、子(Ingredient)も自動で削除される

@enum:

enum Status {
  DRAFT
  PUBLISHED
}

model Post {
  status Status @default(PUBLISHED)
}
  • @enumはDB側に設定を追加するので、後で削除や変更をする際は既存データを消さないとmigrate devが通らなくなる

@@unique:

model User {
  id    Int    @id @default(autoincrement())
  email String @unique
  memos Memo[]
}

model Memo {
  id     Int    @id @default(autoincrement())
  userId Int
  title  String
  body   String?

  user   User   @relation(fields: [userId], references: [id])

  @@unique([userId, title])
}
  • MemoのtitleをUniqueにすることでUserが同じtitleのMemoを持つ事は避けたいとする。しかしUserが複数いることを想定するとtitleをUniqueにしてしまったらあるUserが作成したtitleを他のUserは作れなくなる。

  • @@uniqueで user_idとtitleを紐付けることでユーザー間でtitleが被ることは許容できるようになる。

    • titleの方はnullableでも構わない

idは自動生成

model Bookmark {
  id            String

上記のような場合、create時に毎回 id:uuid()などでidの生成を行わないといけないので、自動生成するようにしたほうが良い。

model Bookmark {
  id            String   @id @default(cuid())
  • 他には @default(uuid())、 @default(autoincrement())がある。

database
/
prisma
orm
postgresql
  • インストール・概要
  • Prisma v7
  • DBスキーマ
  • スクリプトコマンド
  • データが無い場合
  • migrateの使用
  • .gitignore
  • 開発/本番でDBを分ける
  • migrateを途中から取り入れる場合
  • Vercel
  • Prisma Clientの生成
  • connection_limit
  • The database server was reached but timed out
  • モデル
  • モデルの型を使用
  • リレーションも含めた型
  • モデルの内容
  • idは自動生成