「このプロジェクト、いったい何なんですか?」
今の会社のプロジェクトはいわば「フランケンスタック」だった。MyBatisとJPAが同じプロジェクトに共存している。問題は、このコードを書いた“創造主”である初期メンバーが、すでに全員退職していたことだった。
残された私たち、つまり現チームは混乱していた。どんな基準で技術を混在させたのかを説明する文書が一つも残っていなかったからだ。そのせいで状況は悪化する一方だった。
結局、一つのサービスの中で、似たような機能を作るのに、ある人はXMLを掘り、別の人はエンティティを設計するという奇妙な「技術的アナーキー」になっていた。プロジェクトは保守しづらい怪物へと変わっていき、ついに会議が開かれた。
「技術スタックを一つに統一しましょう」

「JPAって遅くて使えないんじゃないですか?」
会議の空気は張りつめていた。特にMyBatisに慣れている同僚たちは、JPAへの統一に強く反対した。彼らの中心的な論点は「速度」だった。
「この前、統計ページをJPAで作ったら読み込みに20秒かかったのを覚えてないですか? SQLを直接書けば1秒で返ってくるのに、私たちが制御しきれないブラックボックスに頼るのは危険です」
たしかに、いくつかの処理はデータの読み込みだけで数十秒かかっていた。でも私は、それは技術の問題ではなく「習熟度」の問題だと確信していた。私はその場でノートPCを開き、問題の「20秒かかるコード」を表示した。
コードはひどいものだった。List<Entity>を取得しているのに、ループのたびに関連オブジェクトごとにDBへ1件ずつアクセスしていた。典型的なN+1問題だった。
「これはJPAが遅いんじゃありません。私たちがJPAに非効率な仕事をさせていたんです。見てください」
私はその場でFetch Joinを適用し、クエリを一発に減らした。デプロイ後、20秒かかっていた読み込みは1秒に縮んだ。同僚たちの表情が変わった瞬間だった。

意外な発見: キメラではなくハイブリッド
JPAへの誤解が解けたなら、今度はJPAで天下統一すればいいのだろうか。ところが実際に分解して見てみると、それも正解ではなかった。
複雑な統計クエリや数十万件規模のExcelダウンロードをJPAで処理しようとすると、オブジェクト変換コストが大きすぎたし、動的クエリを書くのも面倒だった。一方でMyBatisは、この種の作業では圧倒的に直感的で速かった。「他社はこの問題をどう解決しているんだろう?」 もどかしさから、私は夜通しGoogleで検索し、技術ブログを読みあさった。
驚いたことに、多くの技術企業はJPAだけに固執していなかった。複雑な参照性能のためにQueryDSLを使ったり、私たちと同じようにMyBatisを併用したりしているケースも多かった。
私はそこでハッとした。「ああ、先に去った人たちは、何も考えずに混ぜていたわけじゃなかったんだ」
彼らはすでに各ツールの長所と短所を理解していて、意図的に技術ごとに責務を分けていたのだ。ただ、文書化しないまま去ってしまったせいで、後から入った私たちはその意図を知らず、「なぜ統一しなかったのか」と言い争っていただけだった。
JPAの限界を越える: QueryDSLとProjection
ではMyBatisを外して、JPA陣営の技術だけでこの問題を解決できないだろうか。そこで登場するのがQueryDSLとProjectionだ。
// 1. 必要なデータだけを定義したインターフェース(DTOは不要)
public interface DailyStat {
String getDate();
Long getTotalSales();
}
// 2. QueryDSLやJPA Repositoryで取得する
// DBからその2カラムだけをSELECTするので、MyBatis並みに速い
List<DailyStat> stats = repository.findDailySales();
これらの技術を知ってからは、わざわざMyBatisというXML地獄に戻る理由がかなり薄れた。JPAのエコシステムの中でも、十分に高性能なクエリを書けると分かったからだ。
実務アドバイス: 戦うより共存しよう
結局、私たちのチームは「無条件の統一」ではなく、「原則ある共存」を選んだ。(そして長期的にはQueryDSLへの移行を目標にした。)
面白いのは、私たちが生き残るために選んだこの「書き込み(Command)はJPA、読み取り(Query)は専用ツール」という戦略が、アーキテクチャの観点ではCQRS(Command and Query Responsibility Segregation)パターンのごく基本的な形になっていることだ。
大げさにDBを分割しなくても、コードレベルで「命令と参照の責務を分ける」という思想だけで、プロジェクトはずっと整理される。
おわりに: 技術に罪はない
私たちはよく「JPAが最強だ」「いや、実務ではMyBatisのほうが強い」と論争する。でも今回の経験で学んだのは、悪い技術なんて存在しないということだ。あるのは、用途に合わない場面でその技術を使ってしまうことだけだ。
JPAは魔法の杖のようなものだが、呪文を間違えれば爆発する。MyBatisは頑丈なハンマーのようなものだが、何でも釘に見えてしまう。
もし今、レガシーコードや技術の好みの違いでチーム内に摩擦があるなら、少し立ち止まってみてほしい。その混乱の中には、先輩開発者たちの深い思考が隠れているかもしれない。それを見つけて「ルール」に変えること。それこそが、本当に強い開発チームになる道だ。