news 2026/9/20 3:15:49

create-t3-app における Prisma 活用ガイド:型安全 ORM のセットアップ、スキーマ設計、データベース・シーディングまで

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
create-t3-app における Prisma 活用ガイド:型安全 ORM のセットアップ、スキーマ設計、データベース・シーディングまで
  • 开发工具
  • CLI
  • 代码生成

【免费下载链接】create-t3-app

The best way to start a full-stack, typesafe Next.js app

项目地址:https://gitcode.com/gh_mirrors/cr/create-t3-app
点击查看免费下载

Prisma は TypeScript のための ORM であり、schema.prismaファイルでデータベーススキーマとモデルを定義し、バックエンドからデータベースとやり取りするための型安全なクライアントを生成できます。create-t3-app で Prisma を選択すると、CLI がクライアントの初期化からスキーマ生成、環境変数、npm スクリプトまでを一括でセットアップしてくれます。本記事では、生成されるsrc/server/db.tsの設計意図、スキーマファイルの構成、データベースプロバイダの切り替え方、そしてシーディングの実装手順までを、実際のリポジトリのソースコードと照らし合わせながら解説します。

Prisma とは

Prisma は TypeScript 向けのデータベースツールキット(ORM)です。schema.prismaファイルでデータベーススキーマとモデルを宣言的に定義し、そのスキーマから型安全なクライアントを生成することで、SQL を直接書かずにデータベースへアクセスできます。モデル定義に対する型が自動生成されるため、コンパイル時にフィールド名や型の誤りを検出でき、リファクタリング時の安全性も高まります。

create-t3-app では Prisma を選択すると、prismaInstaller が以下のパッケージを自動でインストールします。

  • 開発依存:prisma(CLI/スキーマ管理)
  • 本番依存:@prisma/client(生成されるクライアント本体)
  • PlanetScale を選択した場合:@prisma/adapter-planetscale@planetscale/database

バージョンは dependencyVersionMap.ts に固定マッピングされており、現時点ではprisma@prisma/clientともに^6.6.0、アダプタは@prisma/adapter-planetscale: ^6.6.0が使用されます。npm レジストリへの問い合わせを省くことで、インストールのパフォーマンスも最適化されています。

Prisma Client:src/server/db.tsの設計

Prisma クライアントはsrc/server/db.tsに置かれ、グローバル変数としてインスタンス化されたうえでエクスポートされ、API ルートで使用されます。これは Prisma チームが Next.js 開発時のベストプラクティスとして推奨しているパターンです。

実際の生成テンプレート(db-prisma.ts)を見ると、その設計が明確にわかります。

import { env } from "~/env"; import { PrismaClient } from "../../generated/prisma"; const createPrismaClient = () => new PrismaClient({ log: env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"], }); const globalForPrisma = globalThis as unknown as { prisma: ReturnType<typeof createPrismaClient> | undefined; }; export const db = globalForPrisma.prisma ?? createPrismaClient(); if (env.NODE_ENV !== "production") globalForPrisma.prisma = db;

この実装が解決しているのは、Next.js のホットリロード(Fast Refresh)時に開発サーバが再起動されるたびに Prisma クライアントが多重生成され、データベース接続がリークするという問題です。globalThisにクライアントを保持し、NODE_ENVproduction以外の場合だけグローバルに再利用する、という 2 段構えのパターンによって、開発時の再生成を防いでいます。

また、PrismaClientlogオプションは環境によって切り替わります。

  • 開発環境(development):query(実行 SQL)、errorwarnを出力
  • それ以外(テスト・本番):errorのみ

これにより、開発中はクエリログを確認しながらデバッグでき、本番ではログノイズを抑えられます。

なお、生成されるクライアントの出力先はスキーマのgenerator clientブロックでoutput = "../generated/prisma"と指定され、プロジェクト直下のgenerated/prismaに置かれる点にも注目してください(base.prisma)。

PlanetScale を選んだ場合のクライアント

データベースプロバイダとして PlanetScale を選択した場合は、db-prisma-planetscale.ts がコピーされます。こちらは Prisma のドライバアダプタ機能を使って、PlanetScale 用アダプタを直接クライアントに渡します。

import { PrismaPlanetScale } from "@prisma/adapter-planetscale"; import { env } from "~/env"; import { PrismaClient } from "../../generated/prisma"; const createPrismaClient = () => new PrismaClient({ log: env.NODE_ENV === "development" ? ["query", "error", "warn"] : ["error"], adapter: new PrismaPlanetScale({ url: env.DATABASE_URL }), });

このアダプタを使うため、スキーマ側ではpreviewFeatures = ["driverAdapters"]を有効にしたうえで、relationMode = "prisma"(外部キー制約をデータベース側で強制しない設定)がコメント付きで追加されます(base-planetscale.prisma)。

tRPC コンテキストへの組み込み

create-t3-app では Prisma クライアントがデフォルトで tRPC のコンテキスト に含まれており、各ファイルで個別にインポートするのではなく、コンテキスト経由で利用することを推奨しています。tRPC を使う場合、createTRPCContextは次のようにdbを返します(with-auth-db.ts)。

import { db } from "~/server/db"; export const createTRPCContext = async (opts: { headers: Headers }) => { const session = await auth(); return { db, session, ...opts, }; };

これにより、ルーター内ではctx.dbとして型安全にアクセスできます。実際のルーター実装(with-prisma.ts)では、次のように利用されています。

create: publicProcedure .input(z.object({ name: z.string().min(1) })) .mutation(async ({ ctx, input }) => { return ctx.db.post.create({ data: { name: input.name, }, }); }), getLatest: publicProcedure.query(async ({ ctx }) => { const post = await ctx.db.post.findFirst({ orderBy: { createdAt: "desc" }, }); return post ?? null; }),

ctx.db.post.createctx.db.post.findFirstがコンパイル時に型チェックされるため、フィールド名のタイポや存在しないフィールドへのアクセスを即座に検出できます。

スキーマファイルの構成

Prisma のスキーマファイルはプロジェクトの/prisma/schema.prismaに置かれます。ここでデータベーススキーマとモデルを定義し、Prisma クライアント生成時の元ネタになります。

Prisma を選択した場合、create-t3-app は認証ライブラリの選択(NextAuth.js/Better Auth/なし)とデータベースプロバイダに応じて、適切なスキーマテンプレートをコピーします。インストーラ(prisma.ts)のロジックは以下のとおりです。

const schemaBaseName = packages?.betterAuth.inUse ? "with-better-auth" : packages?.nextAuth.inUse ? "with-auth" : "base"; const schemaSrc = path.join( extrasDir, "prisma/schema", `${schemaBaseName}${ databaseProvider === "planetscale" ? "-planetscale" : "" }.prisma` );

つまり、テンプレートディレクトリ cli/template/extras/prisma/schema 内のbase.prismawith-auth.prismawith-better-auth.prismaと、それぞれの-planetscale版から 1 つが選ばれ、プロジェクトのprisma/schema.prismaに書き出されます。

基本スキーマ(認証なし)

認証を使わない場合のスキーマ(base.prisma)は次のようになります。

generator client { provider = "prisma-client-js" output = "../generated/prisma" } datasource db { provider = "sqlite" url = env("DATABASE_URL") } model Post { id Int @id @default(autoincrement()) name String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt @@index([name]) }

Postモデルは id/name/作成日時/更新日時の最小構成で、@@index([name])によるインデックスも定義済みです。datasourceブロックのurlenv("DATABASE_URL")で環境変数から読み込むため、接続先をコードにハードコードしません。

NextAuth.js と組み合わせた場合

NextAuth.js と Prisma を同時に選択すると、NextAuth.js の Prisma アダプタが要求するUserSessionAccountVerificationTokenの 4 モデルが、公式ドキュメント推奨の値でスキーマファイルに自動生成されます(with-auth.prisma)。

ポイントを整理すると、以下のとおりです。

  • Useridcuid()で自動生成、email@unique
  • AccountproviderproviderAccountIdの複合ユニーク(@@unique([provider, providerAccountId]))、userへのリレーションはonDelete: Cascade
  • SessionsessionToken@uniqueuserへのリレーションはonDelete: Cascade
  • VerificationTokenidentifiertokenの複合ユニーク
  • PostモデルにもcreatedBycreatedByIdが追加され、Userとのリレーションを持ちます

また、Accountモデルのrefresh_tokenaccess_tokenid_tokenには// @db.Textというコメント付きの注釈があります。これは MySQL/SQL Server でString型(VARCHAR)のままではトークンが長すぎて保存できない問題への対策です。create-t3-app のインストーラは、データベースプロバイダがmysqlまたはplanetscaleの場合にこのコメントを自動的に有効化します(schemaText.replace("// @db.Text", "@db.Text"))。SQLite/PostgreSQL を使う場合はコメントのままで問題ありません。

デフォルトのデータベースとプロバイダの切り替え

create-t3-app のデフォルトデータベースはSQLiteです。セットアップ直後からファイルベースで動作するため、開発や PoC(概念実証)を素早く立ち上げるのには最適ですが、同時実行やスケーラビリティの面から本番環境での使用は推奨されません。

使用するデータベースを変更するには、次の 2 点を変更します。

  1. schema.prismadatasourceブロックにあるproviderpostgresqlまたはmysqlに変更
  2. 環境変数DATABASE_URLの接続文字列を対象データベースのものに更新

プロバイダごとの DATABASE_URL

CLI は選択したプロバイダに応じて.env.env.exampleに接続文字列の雛形を書き込みます(envVars.ts)。

プロバイダproviderの値生成されるDATABASE_URLの雛形
SQLite(デフォルト)sqliteDATABASE_URL="file:./db.sqlite"
PostgreSQLpostgresqlDATABASE_URL="postgresql://postgres:password@localhost:5432/<appName>"
MySQLmysqlDATABASE_URL="mysql://root:password@localhost:3306/<appName>"
PlanetScalemysqlDATABASE_URL='mysql://YOUR_MYSQL_URL_HERE?sslaccept=strict'

プロジェクト名(<appName>)は CLI 実行時に入力した名前がそのままデータベース名に使われます。PlanetScale の場合は、PlanetScale のコンソールで「prisma」ドロップダウンから発行された接続 URL を使い、末尾に?sslaccept=strictを付けるというガイドがコメントとして書き込まれます。

インストーラによるスキーマ変換

プロバイダを SQLite 以外にした場合、インストーラはスキーマファイルのprovider = "sqlite"を選択されたプロバイダに置換します。mysqlpostgresqlplanetscaleのマッピングはインストーラ内に定義されており、PlanetScale は内部的にはmysqlとして扱われます。さらに、前述のとおりmysqlplanetscaleでは@db.Text注釈も同時に有効化されます。

ただし、すでにプロジェクトを作成済みの場合は、この変換は自動では行われませんproviderを手で書き換えた後、pnpm db:pushなどでスキーマをデータベースに反映し、.envDATABASE_URLを更新する必要があります。

環境変数のバリデーション

Prisma を使うプロジェクトでは、src/env.jsDATABASE_URLのバリデーションが追加されます(with-db.js)。

DATABASE_URL: z.string().url(),

@t3-oss/env-nextjszodによるこのバリデーションにより、DATABASE_URLが未設定・不正な形式のままnext buildnext devを実行すると、起動時にエラーで検出されます。空文字を未定義として扱うemptyStringAsUndefined: trueの設定と合わせて、環境変数ミスによる実行時トラブルを未然に防ぎます。スキップしたい場合はSKIP_ENV_VALIDATION環境変数を指定します(Docker ビルドなどで有用です)。

package.json に追加される npm スクリプト

Prisma インストーラは、次の 5 つのスクリプトをpackage.jsonに追加します(prisma.ts)。

スクリプト実行されるコマンド用途
postinstallprisma generate依存関係インストール後に自動でクライアント生成
db:pushprisma db pushスキーマをデータベースに直接反映(マイグレーション履歴を作らない)
db:studioprisma studioブラウザベースのデータ閲覧・編集 UI を起動
db:generateprisma migrate dev開発用マイグレーション作成+適用+クライアント再生成
db:migrateprisma migrate deploy本番環境向けに既存マイグレーションを適用

postinstallが設定されているため、pnpm install(またはnpm installyarn)を実行するだけで Prisma クライアントが自動生成され、src/server/db.tsの import が解決されます。

データベースのシーディング

データベースのシーディング(訳註:データベース構築時にダミーデータや初期データを投入すること)は、開発を始める際にテストデータを素早く投入できる非常に便利な機能です。create-t3-app の公式ドキュメントに沿ったセットアップ手順は次のとおりです。

1.seed.tsを作成する

/prismaディレクトリにseed.tsファイルを作成します。

import { db } from "../src/server/db"; async function main() { const id = "cl9ebqhxk00003b600tymydho"; await db.example.upsert({ where: { id, }, create: { id, }, update: {}, }); } main() .then(async () => { await db.$disconnect(); }) .catch(async (e) => { console.error(e); await db.$disconnect(); process.exit(1); });

このサンプルはupsertを使って指定 ID のレコードが存在すれば更新、なければ作成するという冪等(何度実行しても同じ結果)なシーディングです。最後にdb.$disconnect()を呼んで接続を閉じ、エラー時はprocess.exit(1)で異常終了させる、という定番の流れになっています。

なお、上の例のdb.exampleはあくまで雛形です。実際のプロジェクトでは、スキーマで定義したモデル名に合わせてください。現在のリポジトリの基本スキーマ(base.prisma)ではモデルはPostなので、db.post.upsert(...)のようになります。

2.package.jsonにシード設定を追加する

package.jsonscriptsdb-seedを追加し、prismaキーにシード実行コマンドを定義します。

{ "scripts": { "db-seed": "NODE_ENV=development prisma db seed" }, "prisma": { "seed": "tsx prisma/seed.ts" } }

NODE_ENV=developmentを明示しているのは、src/server/db.tsのログ設定がNODE_ENVで切り替わるためです。prisma db seedコマンドがprisma.seedで指定されたコマンドを実行します。

3. TypeScript ランナーを導入する

シードスクリプトは TypeScript で書かれているため、実行できるランナーが必要です。create-t3-app が推奨するのはtsxです。esbuild ベースで非常に高速に動作し、ESM 設定(ts-nodeで必要になるような)が不要という利点があります。ts-nodeや他のランナーでも動作します。

pnpm add -D tsx

4. 実行する

あとは次のコマンドを実行するだけです。

pnpm db-seed

npmyarnを使っている場合は、それぞれnpm run db-seedyarn db-seedと読み替えてください。

まとめ

create-t3-app が生成する Prisma 構成は、単なる ORM の雛形ではなく、「Next.js 開発における実践的な設計」が織り込まれています。

  • グローバルクライアントパターンsrc/server/db.ts)による開発時の接続リーク防止
  • 環境別のログレベル(開発時はqueryerrorwarn、本番はerrorのみ)
  • tRPC コンテキスト経由のdb公開による各ファイルでの個別 import 回避
  • NextAuth.js 連携モデルの自動生成と MySQL 向け@db.Textの自動有効化
  • PlanetScale ドライバアダプタへの透過的な切り替え
  • postinstalldb:pushdb:studiodb:generatedb:migrateという整備済み npm スクリプト

スキーマファイルは cli/template/extras/prisma/schema に、クライアント実装は cli/template/extras/src/server/db に、インストール処理は cli/src/installers/prisma.ts にそれぞれ置かれているため、興味があればぜひ読み進めてみてください。また、環境変数まわりは envVars.ts と src/env.js を、tRPC との連携は tRPC のドキュメント を参照すると、より全体像を把握できます。

関連する公式リソースとしては、Prisma 公式ドキュメント、Prisma GitHub リポジトリ、Prisma Migrate プレイグラウンド、NextAuth.js の Prisma アダプタ解説、PlanetScale 接続ガイドなどが役立ちます。いずれも Prisma のスキーマ記法の詳細やマイグレーションの応用手法を学ぶ際に参照してください。

  • 开发工具
  • CLI
  • 代码生成

【免费下载链接】create-t3-app

The best way to start a full-stack, typesafe Next.js app

项目地址:https://gitcode.com/gh_mirrors/cr/create-t3-app
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 3:15:07

VOC检测仪器选型指南:六大技术路线与七个评估维度

前两年我帮一家化工园区做设备选型&#xff0c;预算充足&#xff0c;甲方开口就要"最先进的光谱质谱一体机"。结果设备到场后&#xff0c;在分析小屋里的第一个夏天就没站稳——环境温度逼近四十五摄氏度&#xff0c;水汽在采样管里冷凝&#xff0c;谱图乱七八糟&…

作者头像 李华
网站建设 2026/9/20 3:14:04

夸克网盘下载限速怎么破?在线解析与直链提取提速方案详解

网盘限速这件事&#xff0c;几乎每个重度用户都经历过。明明家里宽带跑满能到几百兆&#xff0c;下载网盘里的文件却只有几百KB&#xff0c;一个几GB的安装包要挂一整晚。夸克网盘因为空间给得大方、资源分享活跃&#xff0c;用的人越来越多&#xff0c;但"下载慢"的…

作者头像 李华
网站建设 2026/9/20 3:10:15

IntelliJ IDEA 集成 OpenCode 的可信代理配置指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 3:09:04

GPT Image 2画质翻车?提示词降噪指南,从脏糊噪到高清质感

最近有个朋友跟我吐槽&#xff0c;说用 GPT Image 2 生成图&#xff0c;乍一看构图惊艳&#xff0c;放大一看全是问题&#xff1a;皮肤那块脏得像是隔了层灰&#xff0c;边缘毛毛躁躁&#xff0c;暗部噪点像老式数码相机开到 ISO 3200 的样子。这个现象太典型了。我前前后后调了…

作者头像 李华