EOIFQueryDB
2007/03/30 (Fri) 22:07:46 JST
SQL文の発行
これまでは抽象的な処理が中心でしたが、ここから具体的な処理が中心になってきます。
データベース接続の準備ができると、?EODatabaseChannelは?EOFetchSpecificationをSQL文に変換し、データベースアダプタを通して実行します (selectObjectsWithFetchSpecification()
)。次のSQL文は、上記のコードからOpenBaseアダプタによって発行されたものです(実際は1行)。 ?EOFetchSpecificationにセットされたエンティティ名がFROM句に、EOQualifierがWHERE句に反映されています。
SELECT t0.CATEGORY, t0.DATE_RELEASED, t0.MOVIE_ID, t0.POSTER_NAME, t0.RATED, t0.REVENUE, t0.STUDIO_ID, t0.TITLE, t0.TRAILER_NAME FROM MOVIE t0 WHERE t0.MOVIE_ID = 205
eoのキャッシュ
デバッグログを出力してみると気付きますが、フェッチをするたびにこのようなSQL文が生成されます。 ところが、「データベースの現在の状態をeoに即座に反映させる方法 (http://www.apple.co.jp/webobjects/techinfo/datebase/) 」にはこう書かれています。
基本的に、一度fetchされたeoは再度データベースから読み込まれることなく使用されます。このような戦略により、EOFはデータベースとのトラフィックを最小限に押さえています。
これを読むと、一度フェッチされたeoに対して「二度目以降はSQLが発行されない」ように思えますが、そうではありません。 実際には同じeoを取得することになっても、フェッチのたびにSQL文が発行されています。
確かにオブジェクトグラフ内のeoは、同じデータ行に対して1つしか存在しません。 すでにフェッチ済みのeoがあってもSQL文を発行するのは、データ行の更新に備えるためです。 データ行のフェッチ時、状況に応じて以下の処理が行われます。
- データ行がスナップショットよりも新しい場合
- EODatabaseContextのデリゲートを呼び出す (
databaseContextShouldUpdateCurrentSnapshot()
) - 現在のeoを破棄し、更新する (eoをリフレッシュするよう指定した場合)
- EODatabaseContextのデリゲートを呼び出す (
- データ行がスナップショットと同じ場合
- フェッチしたデータ行を破棄する (eoはそのまま)
正確には、データ行はeoではなくスナップショットとしてキャッシュされ、eoの生成や更新時に使われます。 上記に文章にある「トラフィックを押さえる」とは、おそらく「一度フェッチされたデータ行をスナップショットとしてキャッシュすることで、フェッチ時以外はデータベースにアクセスしないようにする」ことだろうと思います。
Inverse Pages: フェッチの舞台裏