Get org.hibernate.LazyInitializationException in spring boot integration test
Asked Answered
G

2

7

I'm trying to write integration test for Spring Boot application. I have Product and GalleryImage domain model. They are in one-to-many relationship.

public class Product {
    ...

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

I have a integration test as below:

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

However, this test gives me a LazyInitializationException. I searched on Google and StackOverFlow, it says that the session is closed after productRepository.findOne(1L), since galleryImages are lazily loaded, so galleryImages.size() gives me this exception.

I have tried to add a @Transactional annotation on the test, but it's still not working.

Gmt answered 17/3, 2016 at 14:27 Comment(3)
You probably need to add @Transactional on top of your test to fix it. But I would probably move your code to service and add annotation to service method.Affectional
I have tried to add @Transactional on test, it didn't work. Do I need to add some configuration to enable @Transactional?Gmt
Do you have a SpringJUnit4ClassRunner for your test?Affectional
A
1

Hibernate Session has been closed after following line productRepository.findOne(1L).

You can try to do Hibernate.initialize(product.getGalleryImages())

public static void initialize(Object proxy)
                   throws HibernateException

Force initialization of a proxy or persistent collection. Note: This only ensures intialization of a proxy object or collection; it is not guaranteed that the elements INSIDE the collection will be initialized/materialized.

To avoid Hibernate.initialize you can create a service.

@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();
  }
}

If you do use Spring Data JPA in you application then dynamic finder is a good alternative.

Affectional answered 17/3, 2016 at 19:8 Comment(0)
B
0

I had similar issues in the past and the solution was indeed adding the @Transactional annotation, but contrarily to what is proposed by @Anton M answer I believe that in this case we should annotate the test instead as proposed here.

It works both ways but the annotation should be placed if and where necessary, i.e. add it on the service if you need it there and not just for testing purposes.

For example, keep this as it was:

public class Product {
    ...

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

And add the annotation here:

@Test
@Transactional
public void testProductAndGalleryImageRelationShip() throws Exception {
    Product product = productRepository.findOne(1L);
    List<GalleryImage> galleryImages = product.getGalleryImages();
    assertEquals(1, galleryImages.size());
}
Botvinnik answered 28/4, 2022 at 10:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.