ORM

オブジェクト指向のコードとリレーショナル DB のテーブルをマッピングするライブラリ

データベース開発ツール

ORM とは

ORM (Object-Relational Mapping) は、プログラミング言語のオブジェクトとリレーショナル DB のテーブルをマッピングし、SQL を直接書かずにデータベースを操作するライブラリである。

ORM の例

ORM の例を以下に示す。

ORM 言語 特徴
Prisma TypeScript 型安全、スキーマファースト
Drizzle TypeScript 軽量、SQL に近い
TypeORM TypeScript デコレータベース
SQLAlchemy Python 最も成熟
GORM Go シンプル

Prisma の使い方

Prisma の使い方のコード例を示す。

// schema.prisma
model User {
  id    String  @id @default(uuid())
  name  String
  email String  @unique
  orders Order[]
}

model Order {
  id     String @id @default(uuid())
  amount Int
  userId String
  user   User   @relation(fields: [userId], references: [id])
}
// 型安全なクエリ
const user = await prisma.user.findUnique({
  where: { id: '123' },
  include: { orders: true }, // リレーションを含む
});
// user の型: User & { orders: Order[] }

ORM vs 生 SQL vs クエリビルダー

ORM と生 SQL vs クエリビルダーの違いを以下にまとめる。

アプローチ 抽象度 型安全
ORM 高い Prisma, TypeORM
クエリビルダー 中程度 Drizzle, Knex
生 SQL 低い pg ライブラリ

ORM の落とし穴

N+1 問題

// ❌ N+1: ユーザーごとに注文を個別取得
const users = await prisma.user.findMany();
for (const user of users) {
  const orders = await prisma.order.findMany({ where: { userId: user.id } });
}

// ✅ include で一括取得
const users = await prisma.user.findMany({ include: { orders: true } });

複雑なクエリ

ORM では表現しにくい複雑なクエリ (ウィンドウ関数、CTE) は生 SQL にフォールバックする。

const result = await prisma.$queryRaw`
  SELECT user_id, SUM(amount) as total
  FROM orders
  GROUP BY user_id
  HAVING SUM(amount) > 10000
`;

DynamoDB と ORM

DynamoDB は RDB ではないため、従来の ORM は使えない。DynamoDB 用のライブラリ (ElectroDB, DynamoDB Toolbox) がある。

Lambda での選択

Lambda での選択を以下にまとめる。

ケース 推奨
RDS + 複雑なリレーション Prisma
RDS + パフォーマンス重視 Drizzle or 生 SQL
DynamoDB AWS SDK 直接 or ElectroDB

現場での応用を知るには関連書籍も役立つ。

この記事は役に立ちましたか?

関連用語

関連する記事