2016-03-17 39 views
4

我正在嘗試爲Spring引導應用程序編寫集成測試。我有Product和GalleryImage域模型。他們處於一對多的關係。在spring引導集成測試中獲取org.hibernate.LazyInitializationException

public class Product { 
    ... 

    @OneToMany(mappedBy = "product") 
    private List<GalleryImage> galleryImages; 
} 

我有如下一個集成測試:

@Test 
public void testProductAndGalleryImageRelationShip() throws Exception { 
    Product product = productRepository.findOne(1L); 
    List<GalleryImage> galleryImages = product.getGalleryImages(); 
    assertEquals(1, galleryImages.size()); 
} 

然而,這個測試給了我一個LazyInitializationException中。我在Google和StackOverFlow上搜索,它說productRepository.findOne(1L)之後會話被關閉,因爲galleryImages是lazily加載的,所以galleryImages.size()給了我這個例外。

我試圖在測試中添加@Transactional註釋,但它仍然不起作用。

+0

你可能需要添加@Transactional上測試的頂部來修復它。但是我可能會將您的代碼移動到服務並向服務方法添加註釋。 –

+0

我試圖在測試中添加@Transactional,但沒有奏效。我是否需要添加一些配置來啓用@Transactional? – Slim

+0

你有測試過的'SpringJUnit4ClassRunner'嗎? –

回答

0

休眠會話已被關閉後,行productRepository.findOne(1L)

你可以嘗試做代理或持續收集Hibernate.initialize(product.getGalleryImages())

public static void initialize(Object proxy) 
        throws HibernateException 

力初始化。 注意:這隻能確保代理對象或集合的初始化;不能保證集合中的元素將被初始化/物化。

要避免Hibernate.initialize您可以創建一個服務。

@Service 
@Transactional 
public class ProductService { 

    @Transactional(readOnly = true) 
    public List<GalleryImage> getImages(final long producId) throws Exception { 
     Product product = productRepository.findOne(producId); 
     return product.getGalleryImages(); 
    } 
} 

如果你使用你的應用程序Spring Data JPA然後動態取景器是一個很好的選擇。

-3

選項1

你有一個集成測試,這樣的假設是:有一個「說法」,因爲大多數集成測試覆蓋了整個MVC。正如您正確地指出的那樣,您的會話(Hibernate Session)在代理被事務返回到視圖之前已關閉。解決此問題的一種方法是使用Open Session In View來保持會話處於打開狀態,直到響應呈現給視圖。請參閱此StackOverFlow answer以瞭解bean配置。

選項2

休眠默認爲所有@OneToMany@ManyToMany關係使用lazy initialization。解決這個問題的另一種方法是設置fetchTypeEager

@OneToMany(mappedBy = "product", fetch = FetchType.EAGER) 
private List<GalleryImage> galleryImages; 

我不會推薦的情況下,第二方法,把查詢返回一個非常大的結果集