TypeScriptプロジェクトにおけるMySQLのイントロスペクション
Prisma ORMでデータベースをイントロスペクト
このガイドでは、3つのテーブルを持つデモ用SQLスキーマを使用します
CREATE TABLE User (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
name VARCHAR(255),
email VARCHAR(255) UNIQUE NOT NULL
);
CREATE TABLE Post (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
title VARCHAR(255) NOT NULL,
createdAt TIMESTAMP NOT NULL DEFAULT now(),
content TEXT,
published BOOLEAN NOT NULL DEFAULT false,
authorId INTEGER NOT NULL,
FOREIGN KEY (authorId) REFERENCES User(id)
);
CREATE TABLE Profile (
id INTEGER PRIMARY KEY AUTO_INCREMENT NOT NULL,
bio TEXT,
userId INTEGER UNIQUE NOT NULL,
FOREIGN KEY (userId) REFERENCES User(id)
);
テーブルのグラフィカルな概要を見るには展開してください
ユーザー
カラム名 | 型 | プライマリキー | 外部キー | 必須 | デフォルト |
---|---|---|---|---|---|
id | INTEGER | ✔️ | いいえ | ✔️ | 自動インクリメント |
name | VARCHAR(255) | いいえ | いいえ | いいえ | - |
email | VARCHAR(255) | いいえ | いいえ | ✔️ | - |
投稿
カラム名 | 型 | プライマリキー | 外部キー | 必須 | デフォルト |
---|---|---|---|---|---|
id | INTEGER | ✔️ | いいえ | ✔️ | 自動インクリメント |
createdAt | DATETIME(3) | いいえ | いいえ | ✔️ | now() |
title | VARCHAR(255) | いいえ | いいえ | ✔️ | - |
content | TEXT | いいえ | いいえ | いいえ | - |
published | BOOLEAN | いいえ | いいえ | ✔️ | false |
authorId | INTEGER | いいえ | ✔️ | ✔️ | false |
プロフィール
カラム名 | 型 | プライマリキー | 外部キー | 必須 | デフォルト |
---|---|---|---|---|---|
id | INTEGER | ✔️ | いいえ | ✔️ | 自動インクリメント |
bio | TEXT | いいえ | いいえ | いいえ | - |
userId | INTEGER | いいえ | ✔️ | ✔️ | - |
次のステップとして、データベースをイントロスペクトします。イントロスペクションの結果は、Prismaスキーマ内のデータモデルになります。
データベースをイントロスペクトするには、次のコマンドを実行します
npx prisma db pull
このコマンドは、.env
で定義されているDATABASE_URL
環境変数を読み取り、データベースに接続します。接続が確立されると、データベースをイントロスペクトし(つまり、データベーススキーマを読み取ります)、その後、SQLからPrismaデータモデルにデータベーススキーマを変換します。
イントロスペクションが完了すると、Prismaスキーマが更新されます
データモデルは現在、次のようになっています(モデルのフィールドは読みやすさのために並べ替えられています)
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(0)
content String? @db.Text
published Boolean @default(false)
authorId Int
User User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1")
@@index([authorId], map: "authorId")
}
model Profile {
id Int @id @default(autoincrement())
bio String? @db.Text
userId Int @unique(map: "userId")
User User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1")
}
model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique(map: "email") @db.VarChar(255)
Post Post[]
Profile Profile?
}
スキーマ定義の詳細については、Prismaスキーマのリファレンスを参照してください。
Prisma ORMのデータモデルは、データベーススキーマの宣言的表現であり、生成されるPrisma Clientライブラリの基盤となります。Prisma Clientインスタンスは、これらのモデルに合わせて調整されたクエリを公開します。
現在、データモデルにはいくつかの軽微な「問題」があります
User
リレーションフィールドが大文字になっており、Prismaの命名規則に従っていません。より「セマンティクス」を表現するためには、User
とPost
間の関係をよりよく説明するために、このフィールドをauthor
と呼ぶと良いでしょう。User
のPost
およびProfile
リレーションフィールド、さらにProfile
のUser
リレーションフィールドはすべて大文字になっています。Prismaの命名規則に従うためには、両方のフィールドを小文字のpost
、profile
、user
にする必要があります。- 小文字にした後でも、
User
上のpost
フィールドはわずかに誤った名前です。それは実際には投稿のリストを参照しているため、より良い名前は複数形のposts
でしょう。
これらの変更は、生成されるPrisma Client APIにおいて重要です。小文字のリレーションフィールドauthor
、posts
、profile
、user
を使用することで、JavaScript/TypeScript開発者にとってより自然で慣用的に感じられるでしょう。そのため、Prisma Client APIを設定できます。
Because リレーションフィールドは仮想的である(つまり、データベースに直接現れない)ため、データベースに触れることなくPrismaスキーマ内で手動で名前を変更できます
model Post {
id Int @id @default(autoincrement())
title String @db.VarChar(255)
createdAt DateTime @default(now()) @db.Timestamp(0)
content String? @db.Text
published Boolean @default(false)
authorId Int
author User @relation(fields: [authorId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Post_ibfk_1")
@@index([authorId], map: "authorId")
}
model Profile {
id Int @id @default(autoincrement())
bio String? @db.Text
userId Int @unique(map: "userId")
user User @relation(fields: [userId], references: [id], onDelete: NoAction, onUpdate: NoAction, map: "Profile_ibfk_1")
}
model User {
id Int @id @default(autoincrement())
name String? @db.VarChar(255)
email String @unique(map: "email") @db.VarChar(255)
posts Post[]
profile Profile?
}
この例では、データベーススキーマはPrisma ORMモデルの命名規則に従っていました(イントロスペクションから生成された仮想リレーションフィールドのみがそれらに従っておらず、調整が必要でした)。これにより、生成されるPrisma Client APIのエルゴノミクスが最適化されます。
しかし、Prisma Client APIで公開されるカラム名やテーブル名に追加の変更を加えたくなる場合があります。一般的な例としては、データベーススキーマでよく使われるsnake_case表記を、JavaScript/TypeScript開発者にとってより自然に感じられるPascalCaseやcamelCase表記に変換することが挙げられます。
snake_case表記に基づいた、イントロスペクションから取得した以下のモデルを想定してください。
model my_user {
user_id Int @id @default(autoincrement())
first_name String?
last_name String @unique
}
このモデルのためにPrisma Client APIを生成した場合、APIにsnake_case表記が引き継がれます。
const user = await prisma.my_user.create({
data: {
first_name: 'Alice',
last_name: 'Smith',
},
})
データベースのテーブル名とカラム名をPrisma Client APIで使用したくない場合は、@map
と@@map
で設定できます。
model MyUser {
userId Int @id @default(autoincrement()) @map("user_id")
firstName String? @map("first_name")
lastName String @unique @map("last_name")
@@map("my_user")
}
このアプローチにより、モデルとそのフィールドに好きな名前を付け、@map
(フィールド名用)と@@map
(モデル名用)を使用して基になるテーブルとカラムを指すことができます。Prisma Client APIは現在、次のようになります。
const user = await prisma.myUser.create({
data: {
firstName: 'Alice',
lastName: 'Smith',
},
})
これについて詳しくは、Prisma Client APIの構成ページをご覧ください。