Prismaで参照先のレコード削除にハマった話

Prismaで参照先のレコード削除にハマった話

Prisma

おはこんにちばんは。最近は Node.js / TypeScript で使用出来る ORM のPrismaを触っています。

そこでハマった、一対多 や 多対多 のようなリレーションをしているテーブルのレコードの削除について、どのような対応したのかを紹介しようと思います。

実行環境

  • Prisma 2.14.0

事象内容

リレーションしているテーブルのレコードに対して、Prisma のDeleteを使うと以下のエラーが発生しました。

1The change you are trying to make would violate the required relation 'XXXX' between the 'XXXX' and 'XXXX' models.

あれ?何か設定漏れてたかなっと思い色々調べた結果、カスケードの削除(参照先が無くなると同時に削除される)が非対応のようでした...

一応、ロードマップ上では対応するよう進んでいるようです。優先度高くないっぽいけど。

更に調べてみると、Pal.js を使うと対応できるよっというコメントがあったので実際に試してみました。

packageを追加

Pal.js を追加していきます。(何故かgraphql入れないと動かんかった。闇)

1yarn add paljs/plugins graphql

事前設定

参照先のレコードをどう扱うか設定していきます。以下の二つが設定可能です。

  • SET_NULL:関連するレコードをにnullに設定します。
  • CASCADE:関連するレコードを削除します。

/// @onDelete(CASCADE)のように設定します。以下は適当な例です。

schema.prisma
1model User {
2 id Int @id @default(autoincrement())
3 /// @onDelete(CASCADE)
4 userDetail UserDetail?
5}
6
7model UserDetail {
8 id Int @id @default(autoincrement())
9 user User @relation(fields: [userId], references: [id])
10 userId Int
11 displayName String
12}
13

削除処理

以下のようにPal.js のDelete処理を行えば、リレーションをしているテーブルのレコードも含めて削除できます。

1export const deleteUser = async (id: User['id']) => {
2 const prismaDelete = new PrismaDelete(prisma)
3 return await prismaDelete.onDelete({
4 model: 'User',
5 where: { id },
6 deleteParent: true
7 })
8}

最後に

暫定対応をご紹介しましたが、Prisma が対応してくれると良いですね。同じようにハマった人の参考になれば幸いです。