「ORMはやめとけ」派の主張、実は間違っているのはどれ?
解説
正解は「SQLインジェクションが増える」です。これは事実と逆で、ORMはむしろSQLインジェクション対策として有効です。ORMはユーザー入力をパラメータとして自動的にエスケープ処理するため、生SQLを手書きするよりも安全にクエリを組み立てられます。セキュリティ面はORMの明確なメリットであり、これを理由に「やめとけ」と主張するのは的外れです。他の3つはいずれもORMに対する正当な批判です。それぞれ見ていきます。N+1問題で大量のクエリが走るORMが批判される代表的な理由です。たとえば「ユーザー一覧と、各ユーザーの投稿を取得する」というコードを考えます。const users = await prisma.user.findMany(); for (const user of users) { const posts = await prisma.post.findMany({ where: { authorId: user.id } }); } ユーザーが100人いれば、最初の1回+ユーザーごとの100回で合計101回のSQLが発行されます。これがN+1問題です。生SQLならJOINを使って1〜2回のクエリで済む処理が、ORMの書き方次第で爆発的に増えてしまいます。多くのORMはEager Loading(includeやprefetch_relatedなど)でこれを回避する機能を持っていますが、意識しないとハマりがちです。複雑なクエリはORMでは書きづらい単純なCRUD操作はORMの得意分野ですが、複数テーブルをまたぐ集計、サブクエリ、ウィンドウ関数などを使う場面ではORM独自の書き方がかえって複雑になります。「ORMの書き方を調べる時間で生SQL書けた」という経験をした開発者は少なくありません。ほとんどのORMは生SQLを実行する手段(Prismaなら$queryRaw、ActiveRecordならfind_by_sql)を提供しているので、複雑な処理はそちらに切り替えるのが現実的です。ORMが生成するSQLが非効率なことがあるORMは汎用的にSQLを生成するため、不要なカラムまですべて取得するSELECT *が走ったり、人間が書けばもっとシンプルになるクエリが冗長に組み立てられたりすることがあります。小規模なうちは問題になりませんが、データ量が増えるとレスポンスに影響が出始めます。ORMが発行しているSQLをログで確認する習慣をつけておくことが重要です。そもそもORMとは何かORM(Object-Relational Mapping)は、データベースのテーブルとプログラミング言語のオブジェクトを対応づける仕組みです。テーブルの行をオブジェクトとして扱えるので、SQLを書かなくてもUser.find(1)のような直感的なコードでデータを取得できます。代表的なORMにはRuby on RailsのActiveRecord、PythonのSQLAlchemy、JavaScriptのPrismaやTypeORMなどがあります。ORMがSQLインジェクションを防ぐ仕組みSQLインジェクションとは、ユーザーの入力にSQL文を紛れ込ませてデータベースを不正に操作する攻撃です。生SQLを文字列結合で組み立てると脆弱性が生まれます。// 危険な例(生SQL + 文字列結合) const query = `SELECT * FROM users WHERE name = '${userInput}'`; この書き方だとuserInputに' OR '1'='1のような文字列を入れられると、全ユーザーのデータが漏洩します。ORMはユーザー入力をプレースホルダーとして処理し、SQL文とデータを分離するため、この種の攻撃が入り込みにくくなります。ただしORMの生SQL実行機能を使う場合は同じ注意が必要です。