web-dev-qa-db-ja.com

メソッドのJPAフェッチタイプを変更する方法はありますか?

エンティティオブジェクトを編集せずに、単一のメソッドで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();
}

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

18
James McMahon

あなたのエンティティの関連付け(@ OneToOne、@ OneToMany、@ ManyToOne)は怠惰な(FetchType.Lazy)と思われます

次に、2つの方法を考えることができます。

A. 2つのjpaクエリを記述します。1つは遅延の関連付けをフェッチし(これは休止状態のデフォルトの方法です)、もう1つは関連付けの積極的な読み込みを明示的に強制するクエリです(クエリの「fetch」キーワードを参照)。

クエリ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)を使用して、エンティティを取得した後(Finderなどを介して)エンティティの遅延関係を強制的にロードします。

 ErrorCode lazyCode = findErrorCodeById(1); 
 //熱心な負荷の関連付け
 Hibernate.initialize(lazyCode); 
16
H2000

JPAでは、フェッチモードは、アノテーションまたはxmlマッピングファイルのいずれかを介して、各永続属性で指定されます。

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

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

永続性.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レイヤーで適切な永続性ユニット用の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だけです。より現実的なシナリオを反映するようにフィールド名を変更しました(デフォルトでは、コレクションとブロブのみが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>
9
Mike

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

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

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

「loadgraph」と「fetchgraph」の違いの詳細については、こちらをご覧ください: JPAのエンティティグラフのFETCHとLOADの違いは何ですか?

1

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

1
zawhtut