EntityManager フェッチ・プランのサポート

FetchPlan は、アプリケーションがリレーションシップにアクセスする必要がある場合、関連付けられたオブジェクトを取得するためにエンティティー・マネージャーが使用するストラテジーです。

例えば、ご使用のアプリケーションに Department と Employee の 2 つのエンティティーがあるとします。Department エンティティーと Employee エンティティーの間のリレーションシップは、双方向の 1 対多のリレーションシップです。1 つの部門には多くの従業員がいますが、1 人の従業員は 1 つの部門にのみ属します。 Department エンティティーがフェッチされると、ほとんどの場合その部門の従業員もフェッチされるため、この 1 対多のリレーションシップのフェッチ・タイプは EAGER に設定されます。

以下に Department クラスのスニペットを示します。

	@Entity
public class Department {

    @Id
    private String deptId;

    @Basic
    String deptName;

		@OneToMany(fetch = FetchType.EAGER, mappedBy="department", cascade = {CascadeType.PERSIST})
		public Collection<Employee> employees;

}

分散環境では、アプリケーションが em.find(Department.class, "dept1") を呼び出して Department エンティティーをキー「dept1」で検索すると、この検索操作によって Department エンティティーとその Department の EAGER フェッチの関係すべてが取得されます。 上記のスニペットの場合、これは部門「dept1」のすべての従業員です。

WebSphere® eXtreme Scale 6.1.0.5 より前では、クライアントは 1 回のクライアント/サーバー・トリップで 1 個のエンティティーを取得したので、1 個の Department エンティティーと N 個の Employee エンティティーを取得するために、N + 1 回のクライアント/ サーバー・トリップが行われました。この N + 1 個のエンティティーを 1 回のトリップで取得すれば、パフォーマンスを改善できます。

フェッチ・プラン

フェッチ・プランを使用すると、リレーションシップの最大項目数をカスタマイズすることによって、EAGER リレーションシップをフェッチする方法をカスタマイズすることができます。 フェッチの項目数は、LAZY 関係に指定された項目数よりも多い EAGER 関係をオーバーライドします。 デフォルトでは、EAGER 関係のフェッチの項目数がフェッチの最大項目数です。 つまり、ルート・エンティティーからナビゲート可能な EAGER である、すべてのレベルの EAGER リレーションシップがフェッチされます。 EAGER リレーションシップは、そのルート・エンティティーから始まるすべてのリレーションシップが EAGER フェッチとして構成される場合、かつこの場合に限り、ルート・エンティティーからナビゲート可能な EAGER です。

前記の例では、Department と Employee のリレーションシップは EAGER フェッチとして構成されるため、Employee エンティティーは Department エンティティーからナビゲート可能な EAGER です。

Employee エンティティーに別の、例えば Address エンティティーへの EAGER リレーションシップがある場合は、Address エンティティーも Department エンティティーからナビゲート可能な EAGER です。 ただし、Department と Employee のリレーションシップが LAZY フェッチとして構成されていた場合は、Address エンティティーは Department エンティティーからナビゲート可能な EAGER ではありません。Department と Employee のリレーションシップが EAGER フェッチ・チェーンを断ち切るからです。

FetchPlan オブジェクトは EntityManager インスタンスから取得できます。 アプリケーションは setMaxFetchDepth メソッドを使用して、フェッチの最大項目数を変更します。

フェッチ・プランは EntityManager インスタンスに関連付けられています。 フェッチ・プランはどのフェッチ操作にも適用されますが、より厳密には次のとおりです。

FetchPlan オブジェクトは可変です。 一度変更すると、後で実行されるフェッチ操作には変更された値が適用されます。

フェッチ・プランによって、EAGER フェッチのリレーションシップのエンティティーをルート・エンティティーを使用して取得するのに 1 回のクライアント/サーバー・トリップで行うのか、または複数回で行うのかが決まるため、フェッチ・プランは分散デプロイメントにとって重要です。

引き続き前述の例において、フェッチ・プランは最大項目数が無限大に設定されている、とさらに考えてみてください。 この場合、アプリケーションが em.find(Department.class, "dept1") を呼び出して Department を検索すると、この検索操作によって 1 個の Department エンティティーと N 個の従業員エンティティーが 1 回のクライアント/サーバー・トリップで取得されます。 ただし、フェッチの最大項目数がゼロに設定されているフェッチ・プランの場合は、Department オブジェクトのみがサーバーから取得されますが、Department オブジェクトの従業員集合がアクセスされるときのみ Employee エンティティーはサーバーから取得されます。

異なるフェッチ・プラン

要件に基づいていくつかの異なるフェッチ・プランがあります。以下のセクションで説明します。

分散グリッドへの影響

重要: OrderBy アノテーションまたは構成を使用してリレーションシップを順序付けている場合は、LAZY フェッチとして構成されていても EAGER リレーションシップであると見なされます。

分散環境でのパフォーマンスの考慮事項

デフォルトでは、ルート・エンティティーからナビゲート可能な EAGER であるすべてのリレーションシップが 1 回のクライアント/サーバー・トリップで取得されます。 これにより、すべてのリレーションシップを使用する予定がある場合は、パフォーマンスを改善することができます。 ただし、ある種の使用に関するシナリオにおいては、ルート・エンティティーからナビゲート可能な EAGER リレーションシップがすべて使用されるとは限らないため、その未使用エンティティーを取得することによってランタイム・オーバーヘッドと処理能力オーバーヘッドがかかります。

そのような場合に、アプリケーションはフェッチの最大項目数を小さな数に設定し、その特定の項目数の LAZY の後ですべての EAGER 関係を作成することで取得するエンティティーの項目数を減らすことができます。 この設定により、パフォーマンスを改善することができます。

前出の Department と Employee と Address の例をさらに続けると、デフォルトで、Department 「dept1」の従業員に関連付けられたすべての Address エンティティーは、em.find(Department.class, "dept1") が呼び出される場合に取得されます。 アプリケーションが Address エンティティーを使用しない場合は、フェッチの最大項目数を 1 に設定することも考えられるため、Address エンティティーは Department エンティティーと一緒には取得されません。