目次 はじめに
前提
環境
Prismaの導入
下準備
DB関連設定
テーブルの生成
データベースの操作
下準備
データの登録
データの取得
データの更新
データの削除
まとめ
はじめに PrismaはNode.jsとTypeScriptのORMです。
業務で使っていますが、なんとなく使っていて基本を理解していなかったので、自己理解の促進も兼ねて、Prismaの基本について徹底的にまとめてみました。
長編になっていますが、一つ一つ確認していくことでPrismaの基本をマスターできるようになっているので、一緒にやっていきましょう。
前提 本記事では以下の環境が整っていることを前提に進めていきます。
・Node.jsが導入されていること ・VS Code(もしくはなんらかの開発用エディタ)が導入されていること ・なんらかのDBが用意されていること
なお、お試しでDBを作成するならRender.comというサービスがおすすめです。 制限はありますが、簡単に、しかも無料でPostgreSQLのDBを構築できます。
Renderを使う場合は、以下の記事の「データベース情報の設定」をご参照ください。
環境 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での書き方を紹介します。 その他の書き方は公式サイトに記載がありますので、参考にしてください。
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というファイルを作成します。
まずはサーバーを起動させる処理を書きます。
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に記載するものとします。 また、必要な箇所のみ抜粋し、関係ない箇所は省略しています。
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です。
ソースを確認します。
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です。
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です。
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にはもっといろいろな処理があるので、次回は応用編として他の処理を紹介する記事を書きたいと思っています。