Contents
Prisma Clientによる型安全なデータアクセス設計
Prisma ORMは自動生成されるTypeScript型によって、SQL注入リスクを最小限に抑えながらも柔軟なクエリ構築が可能になります。この仕組みとリポジトリパターンを組み合わせることで、コードの品質向上が期待できます。
型安全性と設計の重要性
以下のPrisma ClientコードではUser型が自動生成され、findUniqueメソッドの引数が型チェックされます。
|
1 2 3 4 5 6 7 8 9 10 11 |
import { PrismaClient } from '@prisma/client'; const prisma = new PrismaClient(); async function getUser(userId: string) { const user = await prisma.user.findUnique({ where: { id: userId } }); return user; } |
| パラメータ | 型 | 補足 |
|---|---|---|
userId |
string |
Prisma Clientが自動チェック |
ポイント: Prismaの型安全性は、データベーススキーマとコードの整合性を維持するための強力なツールです。
サービス層とリポジトリ層の分離アーキテクチャ
NestJSの@Injectable()デコレータを使ってサービス層を設計すると、依存関係の注入が容易になりテスト性も向上します。これは特に複数データベースとの連携が必要な場合に有効です。
分離アーキテクチャの実装手順
- リポジトリインターフェースを定義
- Prisma Clientに基づくリポジトリ実装
- サービス層でリポジトリを注入
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// user.repository.ts export interface UserRepo { getUser(id: string): Promise<User | null>; } @Injectable() export class PrismaUserRepo implements UserRepo { constructor(private prisma: PrismaClient) {} async getUser(id: string): Promise<User | null> { return this.prisma.user.findUnique({ where: { id } }); } } |
この設計により、テスト時にもダミーのリポジトリを注入可能になります。
MySQL環境でのPrismaアダプター選定
MySQL対応ではPrisma Clientはmysql2パッケージを使用します(※公式ドキュメントに基づく)。mariadbパッケージの導入は、MariaDBとの互換性を求める場合に限定されます。
MySQL環境構築手順
prisma generateで型定義ファイル生成- MySQL 8.0との接続設定ファイルを作成
|
1 2 3 4 5 6 |
// prisma/schema.prisma datasource db { provider = "mysql" url = env("DATABASE_URL") } |
注意: 接続URLに
?sslaccept=strictを付与することで、SSL接続の強制が可能です。
データベースマイグレーションベストプラクティス
Prisma Migrateはデータベーススキーマとコードの同期を自動化しますが、開発・本番環境で一貫した戦略が必要です。
クリーンなワークフロー
prisma migrate devで開発用マイグレーション生成- レビュー後の本番適用は
prisma migrate deploy - ロールバック時は
prisma migrate reset
| 環境 | 実行コマンド | 注意点 |
|---|---|---|
| 開発環境 | prisma migrate dev |
自動コミットされる |
| 本番環境 | prisma migrate deploy |
コミットメッセージの記録が重要 |
Dockerによる環境一貫性確保
Docker ComposeでMySQLとアプリケーションを統合すると、開発・テスト・本番環境での不一致リスクが大幅に軽減されます。
docker-compose.yml構成例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
version: '3.8' services: app: build: . ports: - "5000:5000" depends_on: - db db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: myapp volumes: - db_data:/var/lib/mysql volumes: db_data: |
テスト手順:
docker-compose upで環境構築後、アプリケーションがMySQLに接続できることを確認してください。
テストコードにおけるPrisma Clientのモック化
jestとprisma-mockを使用することで、データベース依存テストを実現できます。これにより、CI/CDでの高速なテストが可能になります。
トランザクション制御テスト例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
import { PrismaMock } from 'prisma-mock'; describe('User Service', () => { let prisma: PrismaMock; beforeEach(() => { prisma = new PrismaMock(); }); it('should rollback on error', async () => { await expect(prisma.user.create({ data: { name: 'Alice' } })) .rejects .toThrowError("Unique constraint failed"); }); }); |
エラーハンドリングとトランザクション制御
Prismaはトランザクションをprisma.$transaction()メソッドでサポートします。複数のDB操作が一括で失敗した場合のロールバックが必要な場合はこれを活用しましょう。
トランザクション実装例
|
1 2 3 4 5 6 7 |
async function updateUserProfile(userId: string, data: any) { return prisma.$transaction(async (tx) => { await tx.user.update({ where: { id: userId }, data }); await tx.profile.update({ where: { userId }, data }); }); } |
ポイント: トランザクション内でエラーが発生すると、自動的にロールバックされます。
結論
本記事ではNestJSとPrismaでMySQLアプリケーションを構築する際のベストプラクティスを解説しました。主なポイントは以下の通りです:
- 型安全性: Prisma Clientによる自動生成型がコード品質を向上
- レイヤー分離: リポジトリ層とサービス層の明確な役割分担
- 環境一貫性: Dockerで開発・本番の一貫性を確保
- テスト設計: Prisma Clientのモッキング手法でCI/CDを効率化
これらの実践方法を取り入れることで、スケーラブルなMySQLアプリケーションの構築が可能になります。記事内のサンプルコードを基に、プロジェクト構成を見直してみましょう。