今回やること
Prisma 7とSQLiteで、ユーザーと投稿のリレーションを操作します。
UserとPostモデルを定義する- migrationでSQLiteにテーブルを作る
- ユーザーと投稿を同時に作る
findManyとincludeで関連する投稿まで読む
SQLiteは1つのファイルで動くデータベースです。この記事では、外部のDBサーバーを用意せずPrismaの基本の流れに集中します。
前提条件
- Node.js 20.19以上(または22.12以上、24以上)
- npm
- TypeScriptのオブジェクトと
async/awaitが読める
node --version
npm --version
プロジェクトを準備する
mkdir prisma-sqlite-practice
cd prisma-sqlite-practice
npm init -y
npm install --save-dev prisma@7 typescript tsx @types/node @types/better-sqlite3
npm install @prisma/client@7 @prisma/adapter-better-sqlite3@7 dotenv
npx tsc --init
npx prisma init --datasource-provider sqlite --output ../generated/prisma
Prisma 7では、Prisma Clientへデータベースに合うdriver adapterを渡します。今回はSQLite用の@prisma/adapter-better-sqlite3を使います。
ESMを設定する
package.jsonへtypeとスクリプトを追加します。依存関係の項目はnpm installが作ったまま残してください。
{
"type": "module",
"scripts": {
"db:migrate": "prisma migrate dev",
"db:generate": "prisma generate",
"start": "tsx script.ts"
}
}
tsconfig.jsonは次の内容に置き換えます。
{
"compilerOptions": {
"module": "ESNext",
"moduleResolution": "bundler",
"target": "ES2023",
"strict": true,
"esModuleInterop": true
}
}
接続先を確認する
初期化によって、ルートの.envに次の設定が作られます。
DATABASE_URL="file:./dev.db"
prisma.config.tsは接続URLとmigrationの保存先を管理します。
import "dotenv/config";
import { defineConfig, env } from "prisma/config";
export default defineConfig({
schema: "prisma/schema.prisma",
migrations: {
path: "prisma/migrations",
},
datasource: {
url: env("DATABASE_URL"),
},
});
Prisma 7では接続URLをschema.prismaへ書かず、prisma.config.tsで設定します。
UserとPostを定義する
prisma/schema.prismaを次の内容にします。
generator client {
provider = "prisma-client"
output = "../generated/prisma"
}
datasource db {
provider = "sqlite"
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String
posts Post[]
}
model Post {
id Int @id @default(autoincrement())
title String
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: Cascade)
}
User.postsとPost.authorが1対多のリレーションです。実際の外部キーはPost.authorIdへ保存されます。
MigrationとClient生成を実行する
npm run db:migrate -- --name init
npm run db:generate
この操作によってmigrationファイル、SQLiteファイル、generated/prismaの型付きClientが作られます。
Prisma Clientを接続する
lib/prisma.tsを作ります。
import "dotenv/config";
import { PrismaBetterSqlite3 } from "@prisma/adapter-better-sqlite3";
import { PrismaClient } from "../generated/prisma/client";
const connectionString = process.env.DATABASE_URL;
if (!connectionString) {
throw new Error("DATABASE_URL is not set");
}
const adapter = new PrismaBetterSqlite3({ url: connectionString });
export const prisma = new PrismaClient({ adapter });
生成先がgenerated/prismaなので、lib/prisma.tsからのimportは../generated/prisma/clientです。別の出力先へ変えた場合は、このimportも一緒に直します。
作成して取得する
ルートにscript.tsを作ります。
import { prisma } from "./lib/prisma";
async function main() {
// このチュートリアルが作るUserだけを再実行前に消す
await prisma.user.deleteMany({
where: {
email: "ada@example.com",
},
});
await prisma.user.create({
data: {
name: "Ada",
email: "ada@example.com",
posts: {
create: [
{ title: "最初の投稿", published: true },
{ title: "下書き", published: false },
],
},
},
});
const users = await prisma.user.findMany({
include: {
posts: true,
},
});
console.log(JSON.stringify(users, null, 2));
}
main()
.then(async () => {
await prisma.$disconnect();
})
.catch(async (error: unknown) => {
console.error(error);
await prisma.$disconnect();
process.exit(1);
});
posts.createはユーザーと関連する投稿をまとめて作ります。include: { posts: true }は、ユーザーだけでなく関連する投稿も結果へ含めます。
再実行時は全データを消さず、チュートリアル用のada@example.comだけを削除します。Post.authorのonDelete: Cascadeにより、そのユーザーに属する投稿も一緒に削除されます。この固定メールを使う削除処理はローカル練習専用です。本番データへ流用しないでください。
成功を確認する
npm start
次のように、1人のユーザーの中に2件の投稿が表示されれば成功です。IDの数値は環境によって異なります。
[
{
"id": 1,
"email": "ada@example.com",
"name": "Ada",
"posts": [
{
"id": 1,
"title": "最初の投稿",
"published": true,
"authorId": 1
},
{
"id": 2,
"title": "下書き",
"published": false,
"authorId": 1
}
]
}
]
よくあるエラー
Cannot find module '../generated/prisma/client'
Clientが未生成か、出力先とimportが一致していません。
npm run db:generate
schema.prismaのoutput = "../generated/prisma"も確認します。
Environment variable not found: DATABASE_URL
ルートの.envにDATABASE_URL="file:./dev.db"があるか確認します。prisma.config.tsとlib/prisma.tsの両方がdotenv/configを読み込む構成です。
schemaを変えてもDBへ反映されない
schemaの変更後は、新しい名前でmigrationを実行します。
npm run db:migrate -- --name add_field
練習
Postへcontent String?を追加し、migrationを作成してください。その後、1件目の投稿へ本文を設定し、実行結果にcontentが含まれることを確認します。
次のステップ
基本のCRUDをSQLで確かめたい場合は、SQL SELECT文の練習へ進んでください。別のTypeScript ORMと比較したい場合は、Drizzle ORMガイドを参照してください。
参考リソース
- Prisma ORM: SQLite quickstart
- Prisma ORM: SQLite connector
- Prisma Migrate: Getting started
- Prisma Client: Relation queries
(最終確認: 2026年7月25日)
← 一覧に戻る