web-dev-qa-db-ja.com

遅延ロードされたJPAコレクションが初期化されているかどうかをテストするにはどうすればよいですか?

外部コードからJPAエンティティを取得するサービスがあります。このサービスでは、このエンティティの属性である遅延ロードされたコレクションを反復処理して、クライアントがDBの現在のバージョンに対して何かを追加したかどうかを確認します。

ただし、クライアントがコレクションに触れたことがないため、まだ初期化されていません。これにより、よく知られた

_org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity._

もちろん、クライアントがコレクションに触れたことがなければ、私のサービスは変更の可能性をチェックする必要はありません。問題は、コレクションが初期化されているかどうかをテストする方法を見つけることができないようだということです。 size()を呼び出して、LazyInitializationExceptionがスローされる場合は知っていると思いますが、そのようなパターンに依存しないようにしています。

どこかにisInitialized()メソッドがありますか?

46
akira

JPA2を使用していますか?

PersistenceUnitUtilには、エンティティの負荷状態を判断するために使用できる2つのメソッドがあります。

例えば組織とユーザーの間に双方向のOneToMany/ManyToOne関係があります。

public void test() {
    EntityManager em = entityManagerFactory.createEntityManager();
    PersistenceUnitUtil unitUtil =
        em.getEntityManagerFactory().getPersistenceUnitUtil();

    em.getTransaction().begin();
    Organization org = em.find(Organization.class, 1);
    em.getTransaction().commit();

    Assert.assertTrue(unitUtil.isLoaded(org));
    // users is a field (Set of User) defined in Organization entity
    Assert.assertFalse(unitUtil.isLoaded(org, "users"));

    initializeCollection(org.getUsers());
    Assert.assertTrue(unitUtil.isLoaded(org, "users"));
    for(User user : org.getUsers()) {
        Assert.assertTrue(unitUtil.isLoaded(user));
        Assert.assertTrue(unitUtil.isLoaded(user.getOrganization()));
    }
}

private void initializeCollection(Collection<?> collection) {
    // works with Hibernate EM 3.6.1-SNAPSHOT
    if(collection == null) {
        return;
    }
    collection.iterator().hasNext();
}
55
dira
org.hibernate.Hibernate.isInitialized(..)

私の知る限り、標準のJPAソリューションはありません。ただし、実際にコレクションを初期化する場合は、ユーティリティメソッドを作成して反復することができます(1回の反復で十分です)。

25
Bozho

他のポスターが示すように、Hibernateにはこのためのメソッドがあります。ただし、純粋なJPAにはこれに対する解決策はありません。

2
robertgoko

eclipselinkの場合、ユーザーはアクセスしようとしているコレクションを_org.Eclipse.persistence.indirection.IndirectList_にキャストし、そのisInstantiated()メソッドを呼び出します。次のリンクに詳細情報があります。

http://www.Eclipse.org/eclipselink/api/1.1/org/Eclipse/persistence/indirection/IndirectList.html#isInstantiated

2
amax