JPAの第1レベルのキャッシュをよく理解していると思いました。しかし、関連するpersistence.xmlファイルの "hibernate.show_sql"をtrueに設定して、私のJEE Msg駆動Bean(JBOSS JPA 2.0)をテストしているときに、私は調整方法を知らないsqlの動作を参照しています。ログで私が期待する上で、1つのデータベースselect文から常にJEE JPAの型付きクエリがDBに...繰り返します。第1レベルのキャッシュ混乱
logger.info("Getting widget by query. Sql should be issued");
TypedQuery<Widget> query = entityManager.createQuery("SELECT w FROM Widget w WHERE w.widgetId = :id", Widget.class);
query.setParameter("id", 1);
// This should go to the db
Widget widget = query.getSingleResult();
logger.info("Getting widget by query again. No sql should be issued");
TypedQuery<Widget> query2 = entityManager.createQuery("SELECT w FROM Widget w WHERE w.widgetId = :id", Widget.class);
query2.setParameter("id", 1);
Widget widget2 = query2.getSingleResult();
logger.info("Getting widget by entity manager find. No sql should be issued");
entityManager.find(Widget.class, 1);
しかし、私は見ることは私を混乱させるは、getSingleResult()文、両方のためのselect文である:ここに私のコードの抜粋です。誰かがこれを説明できますか?注意していただきたいのは、findがSQLのlogging文にならないことに注意してください。また、上記のcreateQueryステートメントにWhere句を入れずに、getSingleResult()ステートメントをgetResultList()ステートメントに変更しても、その実行によって2つのSelectステートメントがデータベースに送られてしまうことに気がつきました。これは、ハイバネート・ロギングと、sqlplusを使用して最初と2番目の文の間に行を挿入したデバッグ・セッションを介して検証されました。 createQuery()とwhere句に関しては、エンティティ・マネージャはすでに知っているほどスマートではなく、与えられた問合せの結果をすでにロードしていますか?前の例では、エンティティマネージャが既にすべてのウィジェットエンティティを読み込んだことを理解してはいけませんか?オブジェクトを表示して等価性検査を行うとき、エンティティマネージャがそれらを適切に管理していることに注意してください(つまり、同じdbテーブル行を参照する2つのオブジェクトはありません)。
L1キャッシュは、クエリから取得されたオブジェクトで動作します。したがって、キャッシュされたオブジェクトを使用します。これは決して照会が実行されるのを妨げず、結果が使用されない可能性があります。クエリ結果キャッシュ!= L1キャッシュ –
@NeilStocktonは非常に真です。クエリが繰り返されるのを防ぐことができる唯一の時間は、前に既にトリガされているレイジーイニットです。 – Gimby
私は理解しているので...上記のように行を追加した場合、エンティティマネージャーはidや何かをチェックして結果に新しい行と既にフェッチされた行を加えたものと思われます。行を追加し、既にロードされた行を更新するようなことをしました。結果は新しい行は含まれますが、更新された行は含まれませんでした。 – BMills