質問

エンティティオブジェクトを編集せずに、単一のメソッドでJPAフェッチタイプを変更する方法はありますか

JPAエンティティクラスで構成される共有ORMレイヤーがあります。このORMレイヤーには、2つのDAOレイヤーがアクセスします。 1つのDAOは私のWebアプリケーション用であるため、レイジーフェッチが必要であり、もう1つのDAOはスレッドセーフであるために積極的なフェッチが必要です。

これは、私のスレッドセーフDAOのメソッド例です

@PersistenceContext(unitName = "PersistenceUnit", type = PersistenceContextType.TRANSACTION)
private EntityManager em;

public ErrorCode findErrorCodeById(short id) {
    return (ErrorCode) em.createNamedQuery("ErrorCode.findById").
            setParameter("id", id).getSingleResult();
}

このメソッド(またはクラス全体)で積極的なフェッチを使用するにはどうすればよいですか

役に立ちましたか?

解決

エンティティの関連付け(@ OneToOne、@ OneToMany、@ ManyToOne)はフェチ遅延(FetchType.Lazy)であると想定しています

次に、2つの方法が考えられます。

A。レイジーの関連付けを取得する2つのjpaクエリ(休止状態のデフォルトの方法)と、関連付けの積極的な読み込みを明示的に強制する2番目のクエリを記述します(クエリの" fetch"キーワードを参照)。

        Query q = HibernateUtil.getSessionFactory().getCurrentSession()
                .createQuery("select c from Category as c" +
                        " left join fetch c.categorizedItems as ci" +
                        " join fetch ci.item as i");


B。 Hibernate.initialize(entity)を使用して、エンティティを取得した後、エンティティの遅延リレーションの強制的な読み込みを強制します(例:ファインダー経由)

ErrorCode lazyCode = findErrorCodeById(1);
// eager load associations
Hibernate.initialize(lazyCode);

他のヒント

JPAでは、注釈またはxmlマッピングファイルのいずれかで、各永続属性にフェッチモードが指定されます。

つまり、目標を達成するためのJPAベンダーにとらわれない方法は、DAOレイヤーごとに個別のマッピングファイルを持つことです。残念ながら、これにはマッピングファイルごとに個別のPersistenceUnitが必要になりますが、少なくとも同じエンティティクラスと同じJPQLクエリを共有できます。

コードスケルトンが続きます。

persistence.xml:

<persistence>
    <persistence-unit name="dao-eager">
        <mapping-file>orm-eager.xml</mapping-file>
    </persistence-unit>

    <persistence-unit name="dao-lazy">
        <mapping-file>orm-lazy.xml</mapping-file>
    </persistence-unit>
</persistence>

orm-eager.xml:

<entity-mappings>
    <entity class="ErrorCode">
        <attributes>
            <basic name="name" fetch="EAGER"/>
        </attributes>
    </entity> 
</entity-mappings>

orm-lazy.xml:

<entity-mappings>
    <entity class="ErrorCode">
        <attributes>
            <basic name="name" fetch="LAZY"/>
        </attributes>
    </entity> 
</entity-mappings>

それは、DAOレイヤーの適切なpersistence-unitのEntityManagerFactoryを作成するだけの問題です。

実際には、2つのマッピングファイルは必要ありません。エンティティでLAZYまたはEAGERを注釈として指定し、XMLマッピングファイルで反対を指定できます(ただし、2つの永続性ユニットが必要です)。

上記のHibernateソリューションよりも少しコードが多いかもしれませんが、アプリケーションは他のJPAベンダーに移植可能でなければなりません。

余談ですが、OpenJPAはFetchGroups(JDOから借用した概念)を使用して、上記のHibernateソリューションと同様の機能を提供します。

最後の警告、FetchType.LAZYはJPAのヒントです。プロバイダーは必要に応じて行を積極的にロードできます。

リクエストごとに更新。

このようなエンティティを検討してください:

@Entity 
public class ErrorCode { 
    //  . . . 
    @OneToMany(fetch=FetchType.EAGER)  // default fetch is LAZY for Collections
    private Collection myCollection; 
    // . . .
}

この場合、2つの永続性ユニットが必要ですが、orm-lazy.xmlのみが必要です。より現実的なシナリオを反映するようにフィールド名を変更しました(コレクションとBLOBのみがデフォルトでFetchType.LAZYを使用します)。したがって、結果のorm-lazy.xmlは次のようになります。

<entity-mappings>
    <entity class="ErrorCode">
        <attributes>
            <one-to-many name="myCollection" fetch="LAZY"/>
        </attributes>
    </entity> 
</entity-mappings>

そしてpersistence.xmlは次のようになります:

<persistence>
    <persistence-unit name="dao-eager">
       <!--
          . . .
         -->
    </persistence-unit>

    <persistence-unit name="dao-lazy">
        <!--
           . . . 
          -->
        <mapping-file>orm-lazy.xml</mapping-file>
    </persistence-unit>
</persistence>

OpenJPAについて誰も言及していないので、ここに答えを掲載します。

OpenJPAでは、以前に遅延設定されたコレクションとフィールドを以下のように積極的にロードできます

    OpenJPAEntityManager kem = OpenJPAPersistence.cast(em);
    kem.getFetchPlan().addField(Order.class, "products");
    TypedQuery<Order> query = kem.createQuery(yourQuery, Order.class);

リファレンス: http: //openjpa.apache.org/builds/1.0.3/apache-openjpa-1.0.3/docs/manual/ref_guide_fetch.html

JPA2で EntityGraphs を使用します。これにより、取得する関連エンティティを定義できます。

https://docs.oracle.com/javaee/7 /tutorial/persistence-entitygraphs002.htm https://docs.oracle.com/javaee/7/tutorial/ persistence-entitygraphs003.htm

NamedQueryを作成し、キー javax.persistence.loadgraph または javax.persistence.fetchgraph でヒントを添付します。グラフで定義した関連エンティティを取得します。

&quot; loadgraph&quot;の違いの詳細を確認できます。および「fetchgraph」」ここ: JPAのエンティティグラフのFETCHとLOADの違いは何ですか

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top