0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Prismaをつかってみる

Last updated at Posted at 2025-01-28

NestJSやら他のフレームワークとの組み合わせや、migrationを前提にした資料ばかりなので、既存のDBに対して使うケースを前提にプレーンな環境で構築してみた。

目標

  • Prismaを使ってみる
  • Prismaで既存のDBに対して操作する
  • PrismaでSQL文を投げる

前提

  • 動作を確認するためにExpressを使う
  • typedSqlを使う

準備

適当な場所に新規ディレクトリを作成して、プロジェクトディレクトリとし、中で下記コマンドを打つ

npm init -y
npm i -S express
npm i -D typescript ts-node prisma @types/node @types/express
npx tsc --init

prisma初期設定

npx prisma init

上記コマンド実行で、prisma/schema.prisma と .env が生成される。

mysqlに変更

こちら、接続したいDBにより内容は変わるが、今回ローカルのdockerで立てた mysql に接続するパターンを記す

prisma/schema.prisma を修正

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

.env を修正

DATABASE_URL="mysql://root:password@localhost:5306/test-db"

DDL

CREATE TABLE `users` (
  `id` int unsigned NOT NULL AUTO_INCREMENT COMMENT 'ユーザID',
  `name` varchar(100) NOT NULL COMMENT 'ユーザ名',
  `createdAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '作成日時',
  `updatedAt` datetime DEFAULT NULL COMMENT '更新日時',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

DML

INSERT INTO `test-db`.users (id, name, createdAt, updatedAt) VALUES
(1, 'userA', '2025-01-20 15:15:48', NULL),
(2, 'userB', '2025-01-27 05:15:48', NULL);

PrismaクライアントのインストールとExpress初期設定

npm install @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

で起動して、 ブラウザでlocalhost:3000にアクセスし、「Server is running」が出力していることを確認。


prisma generate

sqlファイルを扱えるように、prisma/schema.prisma を修正

generator client {
  provider = "prisma-client-js"
+  previewFeatures = ["typedSql"]
}

全ユーザ情報を取得するためのSQL

prisma/sql/getUsers.sql

SELECT `id`, `name`, `createdAt`, `updatedAt`
FROM `users` 
ORDER BY id

idを指定してユーザ情報を取得するSQL

prisma/sql/getUser.sql

SELECT `id`, `name`, `createdAt`, `updatedAt`
FROM `users` WHERE `id` = ?
LIMIT 1

※ 引数の書き方はDBによって違うらしい 参考

下記コマンドでクライアントを生成

npx prisma generate --sql --allow-no-models

※ よくわからんけど、node_modules内のファイルが書き換えられる

上記までの作業で、用意したSQLを投げることができる。
SQLを修正追加した場合事に generate コマンドの実行が必要。

Expressの処理の中でSQLを投げ結果を得る

./index.ts に下記を追記

import { getUser, getUsers } from "@prisma/client/sql";


// id指定でユーザ情報を取得
app.get("/getUser/:id(\\d+)", async (req, res) => {
  const id = req.params.id;

  const users: getUser.Result[] = await prisma.$queryRawTyped(
    getUser(Number(id))
  );

  if (!users || users.length === 0) {
    res.send(`<pre>Not Found.<pre>`);
    return;
  }

  res.send(
    `<pre>User:${JSON.stringify(users[0], (key, value) =>
      typeof value === "bigint" ? Number(value) : value
    )}<pre>`
  );
});

// 全ユーザ情報を取得
app.get("/getUsers", async (req, res) => {
  const users: getUsers.Result[] = await prisma.$queryRawTyped(getUsers());

  const userDisplay = users
    .map(
      (user) =>
        `User ${user.id.toString()}: ${JSON.stringify(user, (key, value) =>
          typeof value === "bigint" ? Number(value) : value
        )}`
    )
    .join("\n");

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

npx ts-node index.ts

で起動して、 ユーザ情報を取得できることを確認。

SQLを直接書いてみる

./index.ts に下記を追記

// id指定でユーザ情報を取得
app.get("/getUser", async (req, res) => {
  const { id } = req.query;

  const users: any[] = await prisma.$queryRawUnsafe(
    `SELECT id, name, createdAt, updatedAt" FROM users WHERE id = ${Number(id)}`
  );

  if (!users || users.length === 0) {
    res.send(`<pre>Not Found.<pre>`);
    return;
  }

  res.send(
    `<pre>User:${JSON.stringify(users[0], (key, value) =>
      typeof value === "bigint" ? Number(value) : value
    )}<pre>`
  );
});

まとめ

generate コマンドを避け得て通りたかったがどうやら避けれ無さそう?
※ 方法あったら教えてください

上記で上げたような簡単なSQLであれば、やはり prisma/schema.prisma にmodelを書いてfindメソッド系で呼び出したりするほうが早そう。

const users = await prisma.user.findMany();

とかね。

javascript, typescriptでのバックエンドの業務をちゃんとやったことがないので、何が正しいのか手探りだけど、数粒の糧にはなったか。。。
※ BEのお仕事ください(切実)

ソース

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?