2010-11-29 52 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中沒有解決方案。