昨日同僚が遭遇した休止状態の問題について。これは休止状態の最も基本的なことです。多くの人がこの問題に遭遇したことがあり、非常に一般的であることは理解していますが、この問題に遭遇すると混乱することがよくあります。
印象を深めるためには、それが何なのか、そしてなぜそうなのかを知る必要があります。
その後、元の Hibernate フレームワークを使用していくつかの検証を行い、実行 SQL 出力コンソールを開いたところ、次の結論に達しました。
前提として、同じトランザクションの途中で次のことが行われます。
1. SQL ステートメント session.createSQLQuery(sql).executeUpdate(); を使用して挿入すると、出力ステーションは SQL ステートメントを使用して session.createSQLQuery(sql).uniqueResult() を実行します。 ; SQL クエリも出力されますが、問題なくデータをクエリできます。
2. Hibernate を使用して操作をカプセル化し、session.save(entity) を使用して挿入します。その後、session.get(entity,id) メソッドを使用してクエリを作成します。また、SQL クエリ ステートメントは出力されませんが、データをクエリすることはできます。トランザクションコミット文が実行されると、挿入されたSQL文が出力されます。
3. Hibernate の session.save(entity); を使用して挿入し、「HQL」ステートメントを使用してクエリを実行します。効果は上記の 2 番目の点と同じです。
4. Hibernate の session.save(entity); を使用して挿入しますが、出力コンソールには挿入された SQL ステートメントが出力されません。 次に、SQL ステートメントを使用して session.createSQLQuery(sql).uniqueResult(); を実行すると、SQL クエリ ステートメントが出力されます。問題が発生したため、データをクエリできませんでした。この場合、session.flush() メソッドを使用し、クエリを実行する前に flash() メソッドを実行すると、出力コンソールに挿入された SQL ステートメントが出力されます。 再度クエリを実行すると、データが得られます。
検証が完了した後、上記の情報を確認しました。4 番目の点については、開発プロセス中に頻繁に発生すると思いますが、多くの人が混乱し続けています。これだけでも印象は深まりました。
印刷コンソール SQL から、基本的な休止状態保存メソッドの操作プロセスを確認できます。
1. 保存するインスタンスがすでに永続状態であるかどうかを確認し、そうでない場合はキャッシュに置きます。
2. 保存するインスタンスに基づいて挿入 SQL ステートメントを計画します。これは計画されるだけで、実行されるわけではないことに注意してください。
3. トランザクションがコミットされると、以前に計画された挿入ステートメントが実行されます。
tx.commit() を session.flush に置き換えます。この時点で、コントロールは挿入ステートメントを出力しますが、新しいレコードはデータベースに追加されません。
フラッシュ メソッドの主な機能は、キャッシュをクリーンアップし、データベースを強制的に Hibernate キャッシュと同期させてデータの一貫性を確保することです。その主なアクションは、一連の SQL ステートメントをデータベースに送信し、これらの SQL ステートメントを実行することですが、それらをデータベースに送信することはありません。 commit メソッドは、まずフラッシュ メソッドを呼び出してから、トランザクションをコミットします。これが、トランザクションがコミットされるまでデータベースへの更新が保存されないため、flush を呼び出すだけではレコードがデータベースに挿入されない理由です。 commit メソッドは暗黙的にフラッシュを呼び出すため、通常はフラッシュ メソッドを明示的に呼び出しません。
これは Hibernate のフラッシュ メカニズムです。一部の複雑なオブジェクトを更新および保存するプロセスでは、データベース操作の順序の変更やフラッシュの遅延がプログラムの結果に影響を与えるかどうかを考慮する必要があります。実際に影響がある場合は、操作の順序を維持する必要がある場所にフラッシュを追加して、キャッシュに記録された操作を Hibernate に強制的にデータベースにフラッシュさせることができます。これは見た目には良くないかもしれませんが、非常に効果的です。
質問: session.save メソッドはキャッシュに置かれており、データベースに直接クエリする SQL では見つけることができません。
flash() メソッドの後、実行された SQL が出力されますが、まだデータベースには存在しません。直接 SQL クエリでデータを検索できます。
1. flash() の後にエンティティ データはどこに保存されますか?キャッシュは save() メソッドと同じであるため、SQL では取得できないはずです。
2. フラッシュ メソッドの後にデータがデータベースに入っていないため、session.createSQLQuery(sql) を使用して SQL を直接クエリできます。クエリしている場所がデータベースではないことを直接確認する必要があります。