JDBC Web アプリケーションを JDO DataNucleus 2.1.1 に移行しようとしています。
次のようなクラスがいくつかあるとします。
public class Position { プライベート整数 ID; プライベート文字列のタイトル。}
public class Employee { プライベート Integer id; プライベート文字列名; プライベート ポジション ポジション; }
Position SQL テーブルの内容は、あまり頻繁に変更されることはありません。JDBC を使用して、テーブル全体をメモリに読み込みます (定期的に、または必要に応じて更新できます)。次に、Employee をメモリに読み込むときに、Employee テーブルから位置 ID を取得し、それを使用してメモリ内の Position インスタンスを取得します。
ただし、DataNucleus を使用して、すべての位置を反復すると、次のようになります。
Extent<Position> extent =pm.getExtent(Position.class, true);
Iterator<Position> iter =extent.iterator();
while(iter.hasNext()) {
Position position =iterPosition.next();
System.out.println(position.toString());
}
その後、別の PersistenceManager を使用して、すべての Employees を反復処理し、Position を取得します。
Extent<Employee> extent =pm.getExtent(Employee.class, true);
Iterator<Employee> iter =extent.iterator();
while(iter.hasNext()) {
Employee employee =iter.next();
System.out.println(employee.getPosition());
}
次に、従業員の職位を取得すると、DataNucleus は 2 つのテーブルを結合する SQL を生成するように見えます。
SELECT A0.POSITION_ID,B0.ID,B0.TITLE FROM MYSCHEMA.EMPLOYEE A0 LEFT OUTER JOIN MYSCHEMA."POSITION" B0 ON A0.POSITION_ID = B0.ID WHERE A0.ID = <1>
私の理解では、利用可能な場合、DataNucleus はキャッシュされた Position インスタンスを使用します。(そうですか?)しかし、結合によってパフォーマンスが低下することが懸念されます。ベンチマークを実行するにはまだ十分ではありません。私の恐れは見当違いですか?続行してベンチマークする必要がありますか? DataNucleus に結合を回避させる方法はありますか?
<jdo>
<package name="com.example.staff">
<class name="Position" identity-type="application" schema="MYSCHEMA" table="Position">
<inheritance strategy="new-table"/>
<field name="id" primary-key="true">
<column name="ID" jdbc-type="integer"/>
</field>
<field name="title">
<column name="TITLE" jdbc-type="varchar"/>
</field>
</class>
</package>
</jdo>
<jdo>
<package name="com.example.staff">
<class name="Employee" identity-type="application" schema="MYSCHEMA" table="EMPLOYEE">
<inheritance strategy="new-table"/>
<field name="id" primary-key="true">
<column name="ID" jdbc-type="integer"/>
</field>
<field name="name">
<column name="NAME" jdbc-type="varchar"/>
</field>
<field name="position" table="Position">
<column name="POSITION_ID" jdbc-type="int" />
<join column="ID" />
</field>
</class>
</package>
</jdo>
私ができることを望んでいるのは、DataNucleus に先に進み、デフォルトのフェッチ グループの一部として POSITION_ID int を読み取り、対応する位置が既にキャッシュされているかどうかを確認するように指示することだと思います。その場合は、そのフィールドを設定します。そうでない場合は、必要に応じて後で参加します。さらに良いことに、その int ID をどこかに隠しておき、後で getPosition() が呼び出されたときにそれを使用します。これにより、すべての場合で結合が回避されます。
クラスと主キーの値を知っていれば、素朴なケースを回避するのに十分だと思いますが、DataNucleus についてはまだ十分に知りません。
いただいた有益なフィードバックにより、私の .jdo はクリーンアップされました。ただし、POSITION_ID フィールドをデフォルトのフェッチ グループに追加した後も、まだ参加しています。
SELECT 'com.example.staff.Employee' AS NUCLEUS_TYPE,A0.ID,A0."NAME",A0.POSITION_ID,B0.ID,B0.TITLE FROM MYSCHEMA.EMPLOYEE A0 LEFT OUTER JOIN MYSCHEMA."POSITION" B0 ON A0.POSITION_ID = B0.ID
なぜそうしているのか理解しています。素朴な方法は常に機能します。私はそれがもっと能力があることを望んでいました。DataNucleus は結果セットからすべての列を読み取るのではなく、キャッシュされた位置を返す場合がありますが、データストアを呼び出して 2 番目のテーブルにアクセスし、それに伴うすべての処理 (ディスクのシークや読み取りを含む) を行います。それがその仕事を放棄するという事実は、ほとんど慰めにはなりません。
私がやりたかったことは、すべての位置がキャッシュされることを DataNucleus に伝えることでした。それを信じてください。何らかの理由でそうでないものを見つけた場合は、キャッシュミスのせいにしてください。Position テーブルで別の選択を (透過的に) 実行する必要があることを理解しています。(さらに良いのは、キャッシュ ミスのために取得する必要があるすべての位置を固定することです。そうすれば、オブジェクトでキャッシュ ミスが再び発生することはありません。)
それが、DAO を介して JDBC を使用して現在行っていることです。永続層を調査する理由の 1 つは、これらの DAO を捨てることでした。単純なフェッチを超えて移動できない永続レイヤーに移動することを想像するのは困難であり、結果として高価な結合が発生します。
Employee が Position だけでなく Department やその他のフィールドを持つとすぐに、Employee fetch によって半ダースのテーブルがアクセスされますが、これらのオブジェクトはすべてキャッシュに固定されており、クラスとクラスを指定してアドレス指定できます。主キー。実際、これを自分で実装して、Employee.position を Integer に変更し、IntIdentity を作成して、それを PersistenceManager.getObjectByID() に渡すことができます。
私が聞いていると思うのは、DataNucleus はこの最適化ができないということです。そうですか?大丈夫です、私が期待したものではありません。