mpssantos
mpssantos

Reputation: 1001

Hibernate Lazyloading not working on @Transactional method

I am facing the so much discussed ""

I'm working on a spring boot application using hibernate.

As far I know, if an attribute of an Entity is marked as FetchType.LAZY, with need to have a Hibernate session to be able to trigger the respective query to bring the related entity.

Following is a method that retrieves a List of entities from a parent entity:

@Transactional
public List<Portfolio> getSharedPortfolios(String userName){
    User user = userService.getUserActive(userName);
    List<Portfolio> sharedPortfolios = user.getSharedPortfolios();
    //logger.debug("Number of Shared Portfolios: " + sharedPortfolios.size());  <======
    return sharedPortfolios;
}

The getSharedPortfolios method is being called from a controller and getting the "org.hibernate.LazyInitializationException" then try to access this List (PersistentBag)

Being getSharedPortfolios method annotated with the @Transactional annotation, i was expecting that when user.getSharedPortfolios() (sharedPortfolios is a Lazy Fetch List) is executed, the respective list is initialized. But is not happening that.

Can someone explain to me why? And Why if i uncomment the log line that prints the size of that PersistentBag, the exception is not thrown?

Do I need in this case explicitly initialise it using EntityManager?

Thank you so much.

Upvotes: 1

Views: 2269

Answers (2)

finrod
finrod

Reputation: 82

I'm not sure what this means

"The getSharedPortfolios method is being called from a controller"

so this might not be your case but the @Transactional annotation will not work if you are calling the getSharedPortfolios method from another method within the same class.

Upvotes: 0

Lesiak
Lesiak

Reputation: 26066

When you call List<Portfolio> sharedPortfolios = user.getSharedPortfolios(); the value assigned to sharedPortfolios is a lazy proxy.

If you simply return sharedPortfolios and access it outside your @Transactional method, you get LazyInitializationException

On the other hand, if you access sharedPortfolios within your @Transactional method, the initialization occurs, and you return already initialized data.

IMHO what you describe is expected behaviour.

There are multiple ways to force the fetch:

  • entity graph
  • jpql (fetch)
  • criteria query (fetch)
  • manually accessing the variable (as shown in your example)

Alternatively, check the setting spring.jpa.open-in-view=true

Upvotes: 2

Related Questions