Prisma + Typescript の実装サンプル

Prisma + Typescript の実装サンプル

〇サンプルに使用するテーブル

CREATE TABLE shopping_items (
    id bigint IDENTITY(1,1) NOT NULL,
    name varchar(40) COLLATE Japanese_CI_AS NOT NULL,
    price int NOT NULL,
    suryo int NULL,
    description varchar(100) COLLATE Japanese_CI_AS NULL,
    version int NOT NULL,
    CONSTRAINT shopping_items_pk PRIMARY KEY (id)
);

Prismaのインストール

Prisma

npm install prisma
npm install -D @types/prisma

Prismaの設定用ファイル作成

npx prisma init

上記のコマンドでprisma/schema.prismaおよび.envファイルが作成される。

schema.prisma:データベース接続変数とスキーマモデルを含む
.env:環境変数 (データベース接続など) を定義する

接続先情報の設定

作成されたファイルを自分のDB接続先情報に書き換える。 schema.prismaに使用するDBを定義し、.envにDB接続先情報を記述する。

〇schema.prisma

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

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

〇.env
接続先情報で設定可能な項目はここを参照

# Environment variables declared in this file are automatically made available to Prisma.
# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema

# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
# See the documentation for all the connection string options: https://pris.ly/d/connection-strings

# connectionLimit, poolTimeoutでコネクションプールの設定ができる
DATABASE_URL="sqlserver://localhost:1433;databaseName=Test;user=aa00001;password=Xaa00001;trustServerCertificate=true;connectionLimit=10;poolTimeout=10"

スキーマ情報作成

以下のコマンドを実行することで、接続先に指定したDBに存在するテーブルのスキーマ情報がschema.prismaに作成される。

npx prisma db pull

以下はスキーマが作成された例である。

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

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

model shopping_items {
  id          BigInt  @id(map: "shopping_items_pk") @default(autoincrement())
  name        String  @db.VarChar(40)
  price       Int
  suryo       Int?
  description String? @db.VarChar(100)
  version     Int
}

model users {
  id         Int    @id(map: "PK_a3ffb1c0c8416b9fc6f907b7433") @default(autoincrement())
  first_name String @db.NVarChar(255)
  last_name  String @db.NVarChar(255)
  age        Int
}

作成されたスキーマは手動で書き換えても良い。 デフォルトで作成されたモデル名やカラム名を変更する場合は@map もしくは@@mapを使用する。

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

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

model ShoppingItems {
  id          BigInt  @id(map: "shopping_items_pk") @default(autoincrement())
  name        String  @db.VarChar(40)
  price       Int
  suryo       Int?
  description String? @db.VarChar(100)
  version     Int
  
  @@map("shopping_items")
}

model users {
  id         Int    @id(map: "PK_a3ffb1c0c8416b9fc6f907b7433") @default(autoincrement())
  firstName String @db.NVarChar(255) @map("first_name")
  lastName  String @db.NVarChar(255) @map("last_name")
  age        Int
}

PrismaClientのインストールと作成

〇インストール

npm install @prisma/client

〇作成

npx prisma generate

DB操作処理記述

index.tsにDB操作を記述する。

import { PrismaClient } from '@prisma/client'
import { ShoppingItems } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
    // ◇ selectサンプル
    const allUsers = await prisma.shoppingItems.findMany();
    console.log(allUsers);

    // ◇ insertサンプル
    await prisma.shoppingItems.create({
        data:{
            name: "オラフ",
            price: 1000,
            suryo: 3,
            description: "ぬいぐるみ",
            version: 1
        }
    });
    
    // ◇ bulkinsertサンプル
    await prisma.shoppingItems.createMany({
        data: [
            { name: 'オラフ',  price: 1000, suryo: 3, description: "ぬいぐるみ", version: 1 },
            { name: 'アンディ', price: 1000, suryo: 3, description: "ぬいぐるみ", version: 1 }, // Duplicate unique key!
            { name: 'スヌーピー',  price: 1000, suryo: 3, description: "ぬいぐるみ", version: 1 },
            { name: 'ベル',  price: 1000, suryo: 3, description: "ぬいぐるみ", version: 1 },
        ]
    });
    
    // ◇ updateサンプル
    await prisma.shoppingItems.update({
        where:{
            id: 20
        }, 
        data:{
            price: 1000,
            suryo: 3,
            description: "ピーナッツ"
        }
    });
    
    // ◇ bulkupdateサンプル
    await prisma.shoppingItems.updateMany({
        where: {
            name: {
            contains: 'オラフ'
            },
        },
        data: {
            suryo: 100
        },
    });
    
    // ◇ deleteサンプル
    await prisma.shoppingItems.delete({
        where: {
            id: 29
        },
    });
    
    // ◇ bulkdeleteサンプル
    await prisma.shoppingItems.deleteMany({
        where: {
            name: {
                contains: 'グラタン'
            }
        }
    });
    
    // ◇クエリを書いて実行サンプル
    // 実行されるSQL:SELECT * FROM shopping_items WHERE description = @P1
    const description = 'ぬいぐるみ';
    const result = await prisma.$queryRaw<ShoppingItems[]>`SELECT * FROM shopping_items WHERE description = ${description}`;
    console.log(result);
}

main()
    .catch((e) => {
    throw e
    })
    .finally(async () => {
    await prisma.$disconnect()
    });

トランザクション処理

import { PrismaClient } from '@prisma/client'

const prisma = new PrismaClient()

async function main() {
    
    // ◇ トランザクションサンプル1
    const [items, count] = await prisma.$transaction([
        prisma.shopping_items.findMany({ where: { name: { contains: 'オラフ' } } }),
        prisma.shopping_items.count(),
    ]);
    console.log(items);
    console.log(count);
    
    // ◇ トランザクションサンプル2
    await prisma.$transaction(async (prisma) => {
        await prisma.shoppingItems.update({
            where:{
                id: 20
            }, 
            data:{
                price: 5000,
                suryo: 3,
                description: "ピーナッツ"
            }
        });
    });
}

main()
    .catch((e) => {
    throw e
    })
    .finally(async () => {
    await prisma.$disconnect()
    });

TypeORMの実装サンプルは以下の記事参照

olafnosuke.hatenablog.com

Sequelizeの実装サンプルは以下の記事参照

olafnosuke.hatenablog.com