2010-11-29 53 views
39

我有一个从外部代码获取JPA实体的服务。在这个服务中,我想迭代一个延迟加载的集合,该集合是该实体的一个属性,以查看客户端是否相对于数据库中的当前版本添加了某些内容。如何测试延迟加载的JPA集合是否已初始化?

但是,客户端可能从未触摸收集,因此它尚未初始化。这导致众所周知的

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

当然,如果客户从未接触过的收集,我的服务没有检查其可能发生的变化。问题是,我似乎无法找到一种方法来测试集合是否已初始化。我想我可以打电话size(),如果它抛出LazyInitializationException我会知道,但我试图不依赖于这种模式。

某处有一些isInitialized()方法吗?

回答

48

您使用的是JPA2吗?

PersistenceUnitUtil具有可以被用于确定一个实体的负载状态的两种方法。

例如组织和用户之间存在双向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(); 
} 
20
org.hibernate.Hibernate.isInitialized(..) 

根据我的知识,没有标准的JPA解决方案。但是如果你想实际初始化集合,你可以创建一个实用程序方法并迭代它们(只有一次迭代就足够了)。

+1

这正是我要找的,谢谢!问题是,即使我碰巧使用Hibernate,代码应该是JPA兼容的,所以不幸的是我没有真正能够使用这个:( – akira 2010-12-01 10:36:38

+1

没有什么标准。 – Bozho 2010-12-01 11:10:21

2

正如另一张海报所示,Hibernate为此提供了一种方法。但是,在纯JPA中没有解决方案。