1
/
5

ゼロからPrismaを導入して、Prismaの基本をマスターしよう

目次

  • はじめに

  • 前提

  • 環境

  • Prismaの導入

  • 下準備

  • DB関連設定

  • テーブルの生成

  • データベースの操作

  • 下準備

  • データの登録

  • データの取得

  • データの更新

  • データの削除

  • まとめ

はじめに

PrismaはNode.jsとTypeScriptのORMです。

業務で使っていますが、なんとなく使っていて基本を理解していなかったので、自己理解の促進も兼ねて、Prismaの基本について徹底的にまとめてみました。

長編になっていますが、一つ一つ確認していくことでPrismaの基本をマスターできるようになっているので、一緒にやっていきましょう。

前提

本記事では以下の環境が整っていることを前提に進めていきます。

・Node.jsが導入されていること
・VS Code(もしくはなんらかの開発用エディタ)が導入されていること
・なんらかのDBが用意されていること

なお、お試しでDBを作成するならRender.comというサービスがおすすめです。
制限はありますが、簡単に、しかも無料でPostgreSQLのDBを構築できます。

Renderを使う場合は、以下の記事の「データベース情報の設定」をご参照ください。

てがるにDB構築:RenderでPostgreSQL環境を作る - Qiita
はじめにアプリケーションを作成する際、DB(データベース)をどのように作成するかも大事になってきます。個人で開発している程度であればあまりDBの構築に時間はかけたくありませんが、設定周りなど結構...
https://qiita.com/course_k/items/b25c326bfb95489d730a#render%E3%81%A7db%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B

環境

OS:macOS 15.1
Node.js:18.20.2

Prismaの導入

下準備

フォルダの作成〜Prismaのインストールまで進めます。

まずは、適当なフォルダを作成しましょう。
本記事では「prisma-basic」という名前で進めていきます。

作成したフォルダをVS Codeで開き、以降はVS Codeのターミナル上で作業を進めます。
以下の通り、フォルダの中身は空です。

npmの初期化を行います。

npm init -y

実行結果は以下のとおりです。package.jsonが生成されます。


次にPrismaとExpressをインストールします。

npm install prisma express

ExpressはNode.jsでの開発を便利にしてくれるフレームワークです。
また、ここでインストールしているPrismaは、「prisma」コマンドが使用可能になるモジュールです。
実際にコードを書く際に使用するモジュールは別にあるので、それはあとで紹介します。


TypeScriptと関連モジュールをインストールし、初期化を行います。

npm install --save-dev typescript ts-node @types/node @types/express
npx tsc --init

tsconfig.jsonが生成されます。

下準備はここまでで完了です。
フォルダ、およびファイル構成は以下のようになっているはずです。


なお、必須ではありませんが、VS Codeを使っている場合は拡張機能をインストールしておくと便利です。
以下のように、prismaと検索して一番上に出てくる機能をインストールします。

これで、後ほど生成されるprismaファイルのシンタックスハイライトなどが可能になります。

DB関連設定

DBの接続情報の設定などを行っていきます。

まず、Prismaの初期化を行います。

npx prisma init

このコマンドで、フォルダ、およびファイル構成は以下のようになっているはずです。

.env
.envは環境変数を定義するファイルで、データベースの接続情報などを定義します。
デフォルトでは仮のDATABASE_URLが設定されています。

prisma
schema.prismaというファイルを持つフォルダです。
schema.prismaはデータベースの様々な情報を定義するファイルです。
他にもprisma関連の自動生成ファイルが配置されていきます。


次に、接続情報の設定を行います。設定はschema.prismaに定義します。
使用するDBによって書き方に違いがありますが、ここではPostgreSQLでの書き方を紹介します。
その他の書き方は公式サイトに記載がありますので、参考にしてください。

Connection URLs (Reference) | Prisma Documentation
Learn about the format and syntax Prisma ORM uses for defining database connection URLs for PostgreSQL, MySQL and SQLite.
https://www.prisma.io/docs/orm/reference/connection-urls#format

schema.prismaのdatasourceブロックに接続情報を記載します。

datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}

provider
接続に使用するDBの種類を記載します。ここでは「postgresql」としています。

url
DBに接続するためのURLです。
ここでは.envファイルに定義した情報を使いたいので、env()に環境変数を渡しています。

実際のファイル内容は以下です。


次に、.envファイルを編集します。
URLの指定方法は以下のとおりです。
なお、Renderを使って構築している場合は「External Database URL」をそのまま設定するだけです。

DATABASE_URL="postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA"

USER
接続に使用するDBのユーザー名

PASSWORD
ユーザー名に紐づくパスワード

HOST
DBサーバーのホスト名

PORT
DBサーバーのポート
PostgreSQLでは省略した場合はデフォルトの5432ポートが使われる

DATABASE
DB名

SCHEMA
DBのスキーマ名
schema=SCHEMAは省略できる
その場合は「public」が使われる

ここまでで接続情報の設定は完了です。

テーブルの生成

生成したいテーブルの情報をschema.prismaに定義します。
schema.prismaの記法にのっとって記載することで、自動でテーブルを生成することができます。

基本形は以下です。

model Model {
Fields Field scalar types Attributes
}

Model
テーブル名
使用できるのは英字の大文字・小文字、数字、アンダースコア
英字始まりでなければならない
通常はパスカルケースで定義する

Fields
カラム名
使用できるのは英の大文字・小文字、数字、アンダースコア
英字始まりでなければならない
通常はキャメルケースで定義する

Field scalar types
カラムの型
String、Int、Boolean、Datetimeなどがある
型の末尾に「?」をつけることで任意の要素​となる
Field scalar typesのその他の型などはこちらのページを参照

Attributes
カラムに設定する属性
「@id」、「@unique」、「@default」などがある
Attributesのその他の属性などはこちらのページを参照

今回はUserというテーブルを作ることにします。

model User {
id Int @id @default(autoincrement())
email String @unique
name String?
age Int
createDate DateTime @default(now())
deleted Boolean @default(false)
}

id列は「@id」属性をつけ、初期値を自動インクリメントにしています。
「@id」はPRIMARY KEY制約に該当する属性で、IDの役割をもつカラムに設定します。
その他、UNIQUE制約や、デフォルト値の設定を行っています。

では、以下のコマンドでテーブル生成を行います。

npx prisma migrate dev --name init

正常に実行されれば、以下のようになります。

このコマンドを実行することで、先ほどのテーブル情報を元にマイグレーション用のSQLが生成されます。
また、生成したSQLを接続情報に設定したDBに対して実行します。

生成したファイルは
prisma > migrations > 実行日時_name
に生成されます。(nameオプションに指定した値が使用される。)

さらに、prisma generateコマンドがバックグラウンドで実行されます。
prisma generateはschema.prismaの定義に基づいて、データモデルを操作するためのファイル等を自動生成します。
このときに生成の元になっているのが、schema.prismaに定義されているgeneratorです。

デフォルトではproviderにprisma-client-jsが設定されています。
これはprisma-client-jsを使用して自動生成するということを指します。
prisma-client-jsには@prisma/clientというモジュールが必要ですが、ない場合には自動でインストールされるので特になにかする必要はありません。

Prismaのインストールの際に触れていた、コードを書く際に必要なモジュールがこの@prisma/clientというわけです。

さて、ここまでできればすべての設定が完了しました。
早速実際にコードを書いて挙動を確かめていきましょう。

データベースの操作

下準備

まずは処理を記述するためのファイルを作成します。

index.tsというファイルを作成します。

まずはサーバーを起動させる処理を書きます。

/* index.ts */

import express from "express";
import { PrismaClient } from "@prisma/client";

const app = express();
const PORT = process.env.PORT || 3000;

const prisma = new PrismaClient();

// ルートパスへのリクエスト
app.get("/", (req, res) => {
res.send("Server is running");
});

// リッスンするポートの設定
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});

これで処理は完了です。
以下のコマンドでサーバーを起動します。

npx ts-node index.ts

以下のURLにアクセスします。

http://localhost:3000/

画面には以下のように表示されます。

データの登録

Userテーブルにデータを登録します。SQLでいうとINSERTです。

まずは先にソースコードの全体を示します。
なお、以降のソースはすべてindex.tsに記載するものとします。
また、必要な箇所のみ抜粋し、関係ない箇所は省略しています。

/* index.ts */
// 他の記載は省略

// 本来は登録時のHTTPメソッドはPOSTを使うが、簡易化のためGETで定義
app.get("/create-user", async (req, res) => {
// クエリパラメータから値を取得
const { email, name, age } = req.query;

const newUser = await prisma.user.create({
data: {
email: String(email),
name: String(name),
age: Number(age),
},
});

res.send(`User created: ${newUser.name}`);
});

今回のポイントは「prisma.テーブル名.create」です。

prisma generateによって、各テーブルごとにcreateのようなメソッドが自動で生成されています。

自動生成されたソースは
node_modules > .prisma > client > index.d.ts
で確認できるので気になる人は確認してみてください。

createメソッドにはdataオブジェクトを指定します。
これは、Userテーブルに登録したいデータのオブジェクトです。

オブジェクトのキーにカラム名を指定すると、バリューに指定した値で登録されます。
※ここでは、クエリパラメータから取得した値は型が適切なものでないので、適宜変換しています。

schema.prismaでの定義時に、「?」をつけたもの、および「@default」を設定したものは任意項目となっているので、設定してもしなくてもよいです。

これから実装の結果を確認しますが、ファイルを編集した場合、サーバーを再起動しないと設定内容が反映されないので、一度サーバーを終了します。

Macの場合はcontrol + C
Windowsの場合はCtrl + C
です。

そして、再度サーバーを起動します。

npx ts-node index.ts

以降の手順でSELECT、UPDATE、DELETEの処理を行いますが、そちらでも同様にしてください。

では、以下のURLにアクセスします。

 http://localhost:3000/create-user?name=John&email=john@example.com&age=25

処理が成功すると、以下の画面が表示されます。

次に、値が正しく登録されているかを確認してみましょう。

データの取得

Userテーブルからデータを取得します。SQLでいうとSELECTです。

ソースを確認します。

/* index.ts */
// 他の記載は省略

app.get("/select-user", async (req, res) => {
const { name } = req.query;
const user = await prisma.user.findFirst({
where: {
name: String(name),
},
});
res.send(`<pre>User selected:${JSON.stringify(user, null, 2)}<pre>`);
});

app.get("/select-all-user", async (req, res) => {
const { name } = req.query;
const users = await prisma.user.findMany();
const userDisplay = users
.map((user) => `User selected: ${JSON.stringify(user, null, 2)}`)
.join("\n");

res.send(`<pre>${userDisplay}<pre>`);
});

2つの処理を作成しました。

使用しているメソッドはfindFirstとfindManyです。

findFirstは取得したデータの1行目を返します。
findManyは複数のデータを配列の形式で返します。

検索条件はwhereオブジェクトとして渡します。
オブジェクトのキーに検索対象のカラム名を設定すると、バリューに指定した値で検索されます。
省略した場合にはWHERE句のないSQLが実行されます。

まずは1行選択のデータを確認します。

 http://localhost:3000/select-user?name=John

先ほど登録したデータが表示されていることが確認できます。

では次に全件取得を試してみます。

 http://localhost:3000/select-all-user

データを1件しか登録していないので代わり映えしませんが、確かに値を取得できることが確認できました。

データの更新

先ほど登録したデータを更新します。SQLでいうとUPDATEです。

/* index.ts */
// 他の記載は省略

// 本来は登録時のHTTPメソッドはPUTを使うが、簡易化のためGETで定義
app.get("/update-user", async (req, res) => {
const { id } = req.query;

const updatedUser = await prisma.user.update({
where: { id: Number(id) },
data: {
name: "Kevin",
age: 30,
},
});

res.send(`Updated: ${updatedUser.name}`);
});

使用しているメソッドはupdateです。

検索条件としてwhereオブジェクト、更新データとしてdataオブジェクトを指定します。
whereオブジェクト、dataオブジェクトの構成は登録、取得で確認したものと同じです。

以下のURLにアクセスするとデータが更新されます。

http://localhost:3000/update-user?id=1

本当に更新されたのか、全件取得処理を使用して確認します。

 http://localhost:3000/select-all-user

指定したデータである、nameとageのみ更新されていることがわかります。

データの削除

最後にデータの削除を確認しましょう。SQLでいうとDELETEです。

/* index.ts */
// 他の記載は省略

// 本来は登録時のHTTPメソッドはDELETEを使うが、簡易化のためGETで定義
app.get("/delete-user", async (req, res) => {
const { id } = req.query;
await prisma.user.delete({
where: { id: Number(id) },
});

res.send("User deleted");
});

使用しているメソッドはdeleteです。

削除の条件をwhereオブジェクトで指定します。

以下のURLにアクセスするとデータが削除されます。

http://localhost:3000/delete-user?id=1

本当に削除されたのか、全件取得処理を使用して確認します。

 http://localhost:3000/select-all-user

1件だけ登録されていたデータを削除したので、何も表示されなくなりました。

まとめ

Prismaの導入、構築から、データの操作までを一気に確認しました。
SQLを書かずとも、簡単な記述でSQLを実行できるのが便利ですね。

また、自動生成されたファイルにより、テーブルの構成に沿った型などが定義されているため、入力補完の恩恵を受けられたり、不正なデータが入りにくくなっているのも良いなと感じました。

本来はエラーハンドリングの処理なども書くのですが、今回はデモのために極力シンプルな処理で実装してみました。

Prismaにはもっといろいろな処理があるので、次回は応用編として他の処理を紹介する記事を書きたいと思っています。

株式会社JOINT CREWからお誘い
この話題に共感したら、メンバーと話してみませんか?
株式会社JOINT CREWでは一緒に働く仲間を募集しています

同じタグの記事

今週のランキング

吉田 光輔さんにいいねを伝えよう
吉田 光輔さんや会社があなたに興味を持つかも