外部コードからJPAエンティティを取得するサービスがあります。このサービスでは、このエンティティの属性である遅延ロードされたコレクションを反復処理して、クライアントがDBの現在のバージョンに対して何かを追加したかどうかを確認します。
ただし、クライアントがコレクションに触れたことがないため、まだ初期化されていません。これにより、よく知られた
_org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity.
_
もちろん、クライアントがコレクションに触れたことがなければ、私のサービスは変更の可能性をチェックする必要はありません。問題は、コレクションが初期化されているかどうかをテストする方法を見つけることができないようだということです。 size()
を呼び出して、LazyInitializationException
がスローされる場合は知っていると思いますが、そのようなパターンに依存しないようにしています。
どこかにisInitialized()
メソッドがありますか?
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();
}
org.hibernate.Hibernate.isInitialized(..)
私の知る限り、標準のJPAソリューションはありません。ただし、実際にコレクションを初期化する場合は、ユーティリティメソッドを作成して反復することができます(1回の反復で十分です)。
他のポスターが示すように、Hibernateにはこのためのメソッドがあります。ただし、純粋なJPAにはこれに対する解決策はありません。
eclipselink
の場合、ユーザーはアクセスしようとしているコレクションを_org.Eclipse.persistence.indirection.IndirectList
_にキャストし、そのisInstantiated()
メソッドを呼び出します。次のリンクに詳細情報があります。