Prisma 基礎
Prismaのドキュメントを読んでみたので、基本的なことをまとめていきます。
Primsaとは
- オープンソースのORM(Object-relational mapping)
- Node上のアプリケーションで直接DBに接続し、クエリー発行が可能
- RDB周りの処理をより簡単に行えるようにし、開発者の生産性を向上させることを目的に開発
- Next.jsアプリケーションでDBを扱う際に特に有用
- Schemaファイルから型情報が生成され、クエリ結果がタイプセーフになる
対応状況
言語
- JavaScript
- TypeScript
- Go (開発途中)
データベース
- PostgreSQL
- MySQL
- SQLite
- SQL Server (開発途中)
主な構成要素
Prisma Model
アプリケーションで使用するモデルを表現する。
モデル内でテーブルやカラムの定義を行う。
また、Prisma Clientでクエリーを発行するために必要となる。
Prisma schema
メインとなる設定ファイル。
下記の要素を定義し、データベースクライアントやマイグレーションファイルの生成を行う。
- データソース: データベースへの接続情報
- ジェネレータ: データモデルを元に生成するデータベースクライアントを指定
- Prisma Model
Prisma Client
データベースクライアント。
Prisma Modelでの型情報を使用して、クエリーの結果は型安全になる。
Prisma Migrate
Prisma Schemaの情報をベースにマイグレーション周りの処理が可能になる。
Prisma Studio
データベース上のデータを閲覧・編集するGUI。
実際の使用手順
1. Prisma schemaファイルの作成
Prismaを使用する際は必ず作成しなければならない。
独自のデータモデリング言語を使用している。
// データベースの接続情報
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
// generateコマンドで生成するものを指定
generator client {
provider = "prisma-client-js"
}
// アプリケーションで使用するモデル
model Post {
id Int @id @default(autoincrement())
title String
content String?
published Boolean @default(false)
author User? @relation(fields: [authorId], references: [id])
authorId Int?
@@unique([authorId, title])
@@index(fields: [title, content], name: "main_index")
}
model User {
id Int @id @default(autoincrement())
email String @unique
name String?
posts Post[]
role Role @default(USER)
}
enum Role {
USER
ADMIN
}
2. Prisma Clientの生成
@prisma/clientをインストール。
npm install @prisma/client
生成コマンドを叩くことで、Prisma schemaを読み、Prisma Clientコードを自動で作成できる。
prisma generate
モデルなどを変更した際は、生成コマンドを再度叩くことで、Prisma Clientコードを更新できる。
生成されたコードはnode_modules/@prisma/clientに置かれ、使用する際はここからインポートする。
3. クエリーの発行
@prisma/clientからインポートして、Prisma Clientインスタンスを作成し、クエリーを発行する。
import { PrismaClient } from '@prisma/client'
// Fetch all posts (in /pages/index.tsx)
export async function getStaticProps() {
const prisma = new PrismaClient()
const posts = await prisma.post.findMany()
return {
props : { posts }
}
}
// Display list of posts (in /pages/index.tsx)
export default ({posts}) =>
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
クエリーの例
- 全ユーザーの取得
const allUsers = await prisma.user.findMany()
- 紐づけられた投稿と一緒に、全ユーザー取得
const allUsers = await prisma.user.findMany({
include: { posts: true },
})
- 「prisma」を含む全投稿を取得
const filteredPosts = await prisma.post.findMany({
where: {
OR: [
{ title: { contains: "prisma" } },
{ content: { contains: "prisma" } },
],
},
})
- ユーザーと投稿を一緒に作成する
const user = await prisma.user.create({
data: {
name: "Alice",
email: "alice@prisma.io",
posts: {
create: { title: "Join us for Prisma Day 2020" },
},
},
})
- 条件に合った投稿の更新
const post = await prisma.post.update({
where: { id: 42 },
data: { published: true },
})
マイグレーション
マイグレーションの実行
このコマンドを実行することで、下記のようなマイグレーションファイルが生成されると同時に実行される。
先述の通り、SchemaファイルのPrisma Modelより生成される。
prisma migrate dev --preview-feature
-- CreateTable
CREATE TABLE "User" (
"id" SERIAL,
"name" TEXT NOT NULL,
PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "Post" (
"id" SERIAL,
"title" TEXT NOT NULL,
"published" BOOLEAN NOT NULL DEFAULT true,
"authorId" INTEGER NOT NULL,
PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "Post" ADD FOREIGN KEY("authorId")REFERENCES "User"("id") ON DELETE CASCADE ON UPDATE CASCADE;
テーブル構造の変更
テーブル構造を変更する際にも、SchemaファイルのPrisma Modelを更新し、同様のマイグレーションコマンドを実行することで、新たなマイグレーションファイルが生成され、実行される。
Discussion
とても参考にできる記事です!
一つprismaに関して質問してよろしいでしょうか?
activeRecordのようなtry catchのtransaction張りたくて、どこ探しても出てこないです。
一応公式には
$transaction
というヘルパーがあるみたいですが、引数として配列のPromiseを渡さなければいけないみたいです。公式ではこういう風に👇書いてます。
やりたいことは、PromiseAで成功して帰ってくるuser_idをPromiseBの引数に入れたいですが、どうやって実現すればいいのかわからないです。
お力貸していただけないでしょうか?
すでに解決しているかもしれませんが、バージョン 2.29.0 より Preview の機能に「Interactive Transactions」という機能が実装されており、トランザクション内で関数を実行することができるようになっています。
Preview の機能のため、
prisma.schema
ファイルにて明示的に有効化する必要があります。詳細は、上記リンクをご参照ください。
ありがとうございます!
ハードコーディングしていたので、試してみます!