我有一个从外部代码获取JPA实体的服务。在这个服务中,我想迭代一个延迟加载的集合,该集合是该实体的一个属性,以查看客户端是否相对于数据库中的当前版本添加了一些内容。
然而,客户可能从未接触过该集合,因此它仍未初始化。这导致了众所周知的
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.example.SomeEntity.
当然,如果客户从未触及过该集合,我的服务无需检查它是否有可能发生的变化。问题是我似乎无法找到一种方法来测试集合是否已初始化。我想我可以在其上调用size()
,如果它抛出LazyInitializationException
我会知道,但我不想依赖这些模式。
某处有isInitialized()
方法吗?
答案 0 :(得分:54)
您使用的是JPA2吗?
PersistenceUnitUtil
有两种方法可用于确定实体的负载状态。
e.g。组织和用户之间存在双向的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();
}
答案 1 :(得分:23)
org.hibernate.Hibernate.isInitialized(..)
据我所知,没有标准的JPA解决方案。但是如果你想实际初始化集合,你可以创建一个实用工具方法并迭代它们(只有一次迭代就足够了)。
答案 2 :(得分:2)
正如另一张海报所示,Hibernate有一个方法。但是,在纯JPA中没有解决方案。
答案 3 :(得分:2)
对于eclipselink
,用户会将您尝试访问的集合转换为org.eclipse.persistence.indirection.IndirectList
,然后调用其isInstantiated()
方法。以下链接提供了更多信息: