どのようにHibernateが私のキャリアをほとんど台無しにしたか
公開: 2022-03-11あなたがJava開発者であり、次の大きなプロジェクトを開始しようとしていると想像してみてください。 プロジェクトの残りの部分であなたに固執する基本的な決定を下す必要があります。 プレーンSQLを扱いたくないので、柔軟なデータモデルの最適なオブジェクト指向の抽象化を選択する必要があります。 あらゆる種類のデータをサポートし、理想的にはあらゆる種類のデータベースをサポートする必要があります。
明白な答えは、 Hibernateを使用することですよね? Java開発者の90%があなたに同意しますが、それは正しい決断ですか?
受け入れられている標準であるという理由だけでHibernateを盲目的に使用すると、何がうまくいかない可能性があるかを見てみましょう。
Java開発者のMonicaについて考えてみましょう。 モニカは最近建築家の役割に昇進し、現在は彼女の会社で新製品のテクノロジースタックをレイアウトする責任があります。 彼女は、Javaの世界では、データベース通信を処理するための優れたツールが1つしかないことを知っています。それはHibernateです。 Hibernateは、よく知られており、サポートされているJPA標準です。 ただし、プロジェクトを開始する前に、いくつかのことを確認することをお勧めします。 幸いなことに、彼女の同僚であるベンは、適切な人を知っています。
休止状態は銀の弾丸のように聞こえます
ベン-こんにちはモニカ、ジョンを紹介したいと思います。 彼はHibernateの専門家であり、あなたを助けるつもりです。
モニカ-ねえジョン、あなたが私のために時間を見つけてくれてうれしい。 ですから、私たちは次の大きなものを構築しています。 次のFacebookやGoogleになることを計画しています。 忙しい日。 それは巨大になるでしょう。 本当に素敵! みんなとても興奮しています! 私は建築家の役割に昇進したので、使用するスタックを選択する必要があります。 唯一欠けている部分は永続性です…
ジョン-休止状態!
モニカ-はい! 丁度! まさに私が考えていたものです! それは私たちにとって完璧な一致と本物の取引のようです。 市場で証明され、長い歴史を持つ真のエンタープライズ問題に対する真のエンタープライズソリューション。 私はそれで非常に多くの前向きな経験を聞いた。 ただし、チームメートの1人に問題があります。 彼は完全にそれに反対しています。 彼はデータベースについて多くのことを知っており、アプリケーションとデータベースの間に別のレイヤーを追加することを恐れています。 彼はとても頭がいいので、これが良い決断だと彼に納得させるには、本当に良い議論が必要です。 それを手伝ってくれませんか。
ジョン-もちろん! 嬉しいです。 Hibernateは確かに優れたツールです。 銀行などの大規模で真のエンタープライズソリューションで広く使用されています。 あなたはそれを間違えることはできません。 永続性を考える: Hibernateを選択します。 Javaで書いている場合、これは絶対に正しい選択であり、さらに他の言語用のポートがあります。 いくつの職務記述書がそれを必要とするか見てください!
モニカ-私は絶対に同意します! 私も同じ気持ちです。 以前のプロジェクトでは、ほとんどの場合、プレーンな古いJDBCを介してSQLを使用していました。 ばかげている! 知っている! しかし、ここに問題があります。チームには本当に賢いSQL担当者がいて、 Hibernateによって生成されたSQLを見ると、緊張しました。 それは醜くて読めないようでした。 これは将来問題になるのでしょうか?
ジョン-見て。 DBAの人たちは別の見方をしています。 プロジェクトでの役割に取って代わるように見えるため、 Hibernateを恐れています。 さらに、データベースにはクエリオプティマイザが組み込まれているため、これらのクエリが実際にどのように表示されるかを心配する必要はありません。 データベースはあなたのためにそれを最適化します。 SQLでは不可能な迅速な開発がすべてです。
モニカ-本当に?! SQLをもう扱っていませんか? すばらしい! 前回、DBAがいくつかのクエリを最適化するために数週間を費やしました。 数週間! ああ、これを言うのはとても恥ずかしいと思いますが、私たちが…ストアドプロシージャを使用していることをご存知でしたか(笑)。 ああ、それはそのような混乱でした。 プロジェクトがまだそれを使用していると信じられますか? 私はそこにいる人々をとても気の毒に思います。 彼らはまだこの退屈なコードを何度も何度も書かなければなりません。 それはまだJavaまたはSQLプロジェクトなのだろうか?
ジョン-それはまさにオブジェクト指向アプローチとリレーショナルアプローチの違いです。 これは、いわゆるオブジェクト指向のインピーダンス不整合です。 Hibernateはこのギャップを埋めることができます。 開発者は、ビジネスロジックの構築に集中できます。 プッシュ機能は、利害関係者と経営陣全体を幸せにします。 最も重要なことをしなさい:ビジネス! 多くの定型コードが消え、ロジックとデータの間に魔法のような目に見えないが信頼できる接続ができます。
モニカ-相互協力。 完全な相乗効果。 データベースのように、最初から言語の一部でした。 この技術的な信仰の飛躍のリーダーになれたことをとてもうれしく思います。 これは、ソフトウェアトレッキングのワープ速度のようなものです。
ジョン-うん! あなたはそれを持っています!
モニカ-おやおや、私はとても興奮しています! ありがとう、ジョン! 準備できました!
柔軟性のないソリューションで成長する痛み
モニカ-ねえジョン、去年話したプロジェクトを覚えてる?
ジョン-もちろん。 調子はどう?
モニカ-まもなく生産を開始します。 すべてが順調ですが、いくつかの質問が出てきました。
ジョン-確かに、私を殴ってください。
モニカ-そうですね、データベーススキーマを最初から生成することはできなくなりました。 データを失うことなくスキーマの変更をサポートするための最良の方法は何ですか?
John-まず、 Hibernateは本番環境移行ツールとして使用することを目的としていません。 FlywayDBやLiquibaseなどを使用してください。 とても簡単です。 移行スクリプトを書き留めてから、 Hibernateマッピングとともにエンティティモデルを更新して、実際のデータベース構造との同期を維持します。
モニカ-うーん、なるほど。 前のプロジェクトでは、単純なSQL移行を使用していました。
ジョン-それも結構です。 エンティティモデルとスキーマの同期を維持している限り、好きなように実行してください。
モニカ-なるほど。 別のことがあります。 私たちは常に怠惰な/熱心なフェッチの問題に苦しんでいます。 ある時点で、すべてを熱心にやろうと決心しましたが、それは最適ではないようです。また、セッションがないなどの理由で、一部のフィールドにアクセスできない場合もあります。 それは正常ですか?
John - Hibernateについてもっと学ぶ必要があります。 データベースからのマッピングは簡単ではありません。 基本的に、それを行うには複数の方法があります。 あなたはただあなたのために働く方法を選ぶ必要があります。 遅延フェッチを使用すると、これらのオブジェクトをオンデマンドで読み込むことができますが、アクティブなセッション内で操作する必要があります。
モニカ-最終的な展開に使用するデータベースエンジンについては、まだ苦労しています。 Hibernateは移植性があると思いましたが、MS SQLの魔法を使用するネイティブクエリがいくつかあり、実際には本番環境でMySQLを使用したいと考えています。
John - Hibernateは、分離基準またはHQLを使用している限り、柔軟性を提供します。 ネイティブクエリは、ソリューションをデータベースにバインドするだけです。
モニカ-そのときはMSSQLに固執する必要があるようです。 最後の質問:私のチームメイトは、HQLには「制限」キーワードはないと言いました。 彼は冗談を言っていると思いましたが、私もそれを見つけることができませんでした。 愚かな質問でごめんなさい…
John-確かに、HQLには「limit」キーワードはありません。 これはデータベースベンダー固有であるため、クエリオブジェクトを介して制御できます。
モニカ-他のすべての要素がHQLにあるのは奇妙に思えます。 どうでも。 御時間ありがとうございます!
SQLでソリューションをまとめてハッキングしています
モニカ-ジョン、最初はSQLを扱うつもりはありませんでしたが、今はそうしなければならないようです。 私たちのニーズは高まっており、それを回避する方法はないようです。 違和感はありますが、日常的にSQLを使い始めています。

ジョン-まあ、それは間違いではありません。 最初はデータベースに集中する必要はありませんでした。 ただし、プロジェクトが成長するにつれて、SQLを使用してパフォーマンスの最適化に取り組むことをお勧めします。
モニカ-時々私たちはエラーを探すのに何日も費やします。 Hibernateで生成されたSQLを分析する必要があるようです。これは、SQLが期待どおりに機能せず、予期しない結果が生じる理由がわからないためです。 Hibernateバグトラッカーでよく知られているいくつかの問題が発生しました。 さらに、エンティティモデルの同期を維持しながら、適切な移行を作成することは困難です。 Hibernateの内部について多くを学び、それがどのように機能するかを予測する必要があるため、時間がかかります。
ジョン-常に学習曲線があります。 たくさん書く必要はありませんが、それがどのように機能するかを知る必要があります。
モニカ-より大きなデータセットでの作業も面倒です。 最近、データベースに大量のインポートを実行しましたが、非常に遅くなりました。 次に、セッションを高速化するためにセッションをクリアする必要があることがわかりました。 それでも、それでもかなり遅いので、プレーンSQLステートメントとして書き直すことにしました。 面白いのは、プレーンSQLを書くことが実際にそれを行う最も速い方法だったので、最後のオプションとしてそれを行うことにしました。
John-インポートはオブジェクト指向のプロセスではありません。 Hibernateはオブジェクト指向設計に焦点を当てています。 ネイティブクエリはいつでも使用できることを忘れないでください。
モニカ-Hibernateキャッシュがどのように機能するかを理解するのを手伝ってくれませんか? わからない。 いくつかの第1レベル/第2レベルのキャッシュがあります。 これはどういうことですか?
ジョン-もちろん。 これは、永続データのいわゆるトランザクションレベルのキャッシュです。 クラスごとおよびコレクションごとに、クラスターまたはJVMレベルのキャッシュを構成することができます。 クラスタ化されたキャッシュをプラグインすることもできます。 ただし、キャッシュは、別のアプリケーションによって永続ストアに加えられた変更を認識しないことに注意してください。 ただし、期限切れのキャッシュデータを定期的に削除するように構成できます。
モニカ-すみません、私は悪い日を過ごしていると思います。 これについてもう少し説明していただけますか?
ジョン-もちろん。 オブジェクトを渡してsave
、 update
、 saveOrUpdate
、またはload
、 get
、 list
、 iterate
、またはscroll
を介してオブジェクトを取得するたびに、そのオブジェクトはセッションの内部キャッシュに追加されます。 オブジェクトとそのコレクションを第1レベルのキャッシュから削除することもできます。
モニカ-えー…
John-さらに、キャッシュモードを制御できます。 normal
モードを使用して、アイテムを第2レベルのキャッシュに読み書きできます。 get
モードを使用して2番目のレベルから読み取りますが、書き戻すことはできません。 put
を使用します。これは、 get
と同じですが、2番目のレベルから読み取ることはできません。 refresh
モードを使用することもできます。これは、第2レベルに書き込みますが、そこから読み取らず、 use minimal puts
プロパティをバイパスして、データベースから読み取られたすべてのアイテムに対して第2レベルのキャッシュを強制的にリフレッシュします。
モニカ-なるほど。 Ok。 これについて考えさせてください。 ああ、遅いです、私は行く必要があります。 御時間ありがとうございます!
ジョン-どういたしまして!
休止状態をあきらめる
モニカ-ジョン、私たちはソフトウェア開発の新時代に入っていると思いました。 私たちは光年のジャンプをしていると思いました。 しかし、4年経った今でも、同じ問題を別の角度からしか扱っていないようです。 Hibernateアーキテクチャ、構成、ロギング、命名戦略、タプリザー、エンティティ名リゾルバー、拡張識別子ジェネレーター、識別子ジェネレーターの最適化、ユニオンサブクラス、XDocletマークアップ、インデックス付きコレクションとの双方向アソシエーション、ターナリアソシエーション、idbag、暗黙のポリモーフィズムの混合を学ぶ必要がありました他の継承マッピング、2つの異なるデータストア間でのオブジェクトの複製、分離オブジェクトと自動バージョン管理、接続解放モード、ステートレスセッションインターフェイス、コレクションの永続性の分類、キャッシュレベル、レイジーまたはイーガーフェッチなど。 私が知っていることすべてをもってしても、私たちはひどく失敗したようです。 それはソフトウェアの大失敗です! 究極の失敗! 災害! ハルマゲドン!
ジョン-待って! どうしたの?
モニカ-行き止まりになりました。 私たちのアプリケーションのパフォーマンスは途方もなく遅いです! レポートを取得するには、2日間待つ必要があります。 顧客のダッシュボードを実際に生成するための2日間。 これは、ダッシュボードがますます時代遅れになる一方で、毎日計算テールを増やす必要があることを意味します。 私たちのDBAエキスパートは、いくつかのクエリを最適化するために2か月間取り組んできましたが、データベース構造は完全に混乱しています。 彼をサポートしている開発者がいますが、問題はDBAがSQLで考えていることであり、開発者はこれを分離された基準またはHQL形式に変換しようと何日も費やしています。 現時点ではパフォーマンスが非常に重要であるため、可能な限りネイティブSQLを使用するようにしています。 とにかく、データベーススキーマが間違っているように見えるので、私たちは多くを行うことができません。 オブジェクト指向の観点からは正しいと感じましたが、リレーショナルの観点からはばかげているようです。 私は自分自身に問いかけています:これはどのように起こったのですか? 開発者は、エンティティ構造の変更は多大な労力を要すると言っているので、それを買う余裕はありません。 前回のプロジェクトではめちゃくちゃだったのを覚えていますが、こんなに重要なポイントにたどり着くことはありませんでした。 データを操作するためのまったく異なるアプリケーションを作成することができました。 現在、エンティティモデルが常に適切に動作することを確認するのは非常に難しいため、これらの生成されたテーブルを変更するのは危険です。 そして、これは最悪の部分でもありません! パフォーマンスを向上させるには、データベースの問題だけでなく、データベースとアプリケーションの間のレイヤー全体の問題も解決する必要があります。 圧倒的です! 私たちにはこれらの新しい人がいます、あなたが知っている、コンサルタント。 彼らはデータを抽出し、それを他のストレージに入れて、外部から計算を実行しようとしています。 時間がかかりすぎです!
ジョン-何と言ったらいいのかわからない。
モニカ-ジョンが見えます。 私はあなたを責めたくない。 私はこれらすべての問題を解決するためにHibernateを選びましたが、今ではそれが特効薬ではないことを学びました。 ダメージがあり、元に戻せません。 実際、私はあなたに何かを聞きたいと思います:私は私のキャリアの最後の4年間をHibernateのものを扱って過ごしました。 現在の会社には未来がないようです。 手伝って頂けますか?
では、学んだ教訓は何ですか?
ジョン-ねえ、ピーター、モニカを紹介させてください。
ピーター-ねえ、モニカ! 私たちはあなたが知っている新しい次の大きなものを構築しています。 巨大になりそうです! Uberのようになりたい! 多分どれだけ持続性があるか知っていますか…
モニカ-冬眠ではありません!
要約
MonicaはHibernateのエキスパートです。 ただし、この場合のHibernateは間違った決定でした。 彼女が自分の解決策が元の問題よりも大きな問題になったことを発見した瞬間、それはプロジェクト全体にとって最大の脅威でした。
データはアプリケーションの中心的な目的であり、それが好きであろうとなかろうと、アーキテクチャ全体に影響を与えます。 話から学んだように、Javaアプリケーションがデータベースを使用しているという理由だけで、または社会的証明のために、 Hibernateを使用しないでください。 柔軟性を取り入れたソリューションを選択してください。 JdbcTemplateやFluentJDBCWrapperなど、堅牢なJDBCラッパーには多くのオプションがあります。 あるいは、jOOQなどの他の強力なソリューションがあります。