TypeScriptでバックエンドを書いちゃう皆様、ORMは何をお使いですか?
私はシェアが大きい Prismaを使ってみたんですが、どうも肌に合いません。その理由は以下のようなものです。
1. 独自スキーマ定義はいらない
ORMの特徴として、テーブルのスキーマに合わせてカラムの型、ENUM、外部キー、ユニーク制約などを生成してくれます。
Prismaはこれを独自のDSLで実現し、npx prisma generate
でスキーマを生成します。
自分だけかもしれませんが、ORMのスキーマに細かいリレーションシップの定義は不要です。
ActiveRecordの hasMany
的な定義を事前に入れるのはだるいし、JOIN条件はクエリの内部に書きたい。
自分が求めるのはコンパイルできるSQL(このカラムねぇよ、そんなJOINできませんよ)であって、それ以上の機能は不要。
Prismaのようなスキーマ生成をする場合、その作業をnode.jsのコンテナに入れないといけない。その場合、GAEの無料インスタンスに乗らないんですね。それも個人的な都合でネックでした。だって、無料で充分まわるんだもん、業務系のシステムってユーザー数が少ないからw
2. Prismaは集約系の機能が弱い
業務系システムやWebサービスの管理画面系になると、GroupByを使わない日は無いと思います。Prismaの独自DSLによって、GroupByの条件を指定するのがとてもだるいです。また、GroupByした時、JOINできないのも勘弁してほしかった。CTEとかもどこまでサポートしているか怪しい。
3. DB独自の関数が利用できない
これはPrismaが意図的にやっていることであって、あう・あわないはあると思います。よく使うのが、MySQLだと date_format
関数などで、それが使えないのは困った。また、includeした場合のクエリの挙動も独特で、それも合わなかった。ORMだから、ある程度発行できるSQLに制御できない部分があるとは思うけど、ちょっとなっていう。
SQLを意識せずDBから値を取ってこれるメリットを何も感じないんですよね。僕はSQLをバチバチに意識したい。クエリビルダ型じゃないといやってことに気づきましたw
Prismaも良いところは色々あって、クライアントを拡張できること。ページネーション用の関数を生やしたり、RLSに対応したり、クエリを発行する前に where tenant_id = 2
みたいなマルチテナントやる時に必須のWHEREを付け加えたり、クエリ発行後にログを出したりイベント発行したりできる。ミドルウェア的な機能が欲しい場合、現状Prisma一択だと思う。
今の自分は、それが必要じゃなかった。
というわけで Drizzleに手を出したんですけど、何回やっても、MySQLのautoIncrementを設定したテーブルにINSERTできなくて... Issue上げたけどまったく無視されており、どうしていいかわからん。Issueの数がすごく多くて、怖くて使えたもんじゃない。
そうなると、残るクエリビルダ型が、KYSELYになる。これが最も自分の好みに近い。良い意味で安定していそう。
TypeScriptのORMを探すたびは続く。