Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 418 Vote(s) - 3.48 Average
  • 1
  • 2
  • 3
  • 4
  • 5
How to solve the “failed to lazily initialize a collection of role” Hibernate exception

#11
I know it's an old question but I want to help.
You can put the transactional annotation on the service method you need, in this case findTopicByID(id) should have

@Transactional(propagation=Propagation.REQUIRED, readOnly=true, noRollbackFor=Exception.class)

more info about this annotation can be found [here][1]

About the other solutions:

fetch = FetchType.EAGER

is not a good practice, it should be used ONLY if necessary.

Hibernate.initialize(topics.getComments());

The hibernate initializer binds your classes to the hibernate technology. If you are aiming to be flexible is not a good way to go.

Hope it helps

[1]:

[To see links please register here]

Reply

#12
In my case following code was a problem:

entityManager.detach(topicById);
topicById.getComments() // exception thrown


Because it detached from the database and Hibernate no longer retrieved list from the field when it was needed. So I initialize it before detaching:

Hibernate.initialize(topicById.getComments());
entityManager.detach(topicById);
topicById.getComments() // works like a charm
Reply

#13
The problem is caused by accessing an attribute with the hibernate session closed. You have not a hibernate transaction in the controller.

Possible solutions:

1. **Do all this logic, in the service layer**, (with the @Transactional), not in the controller. There should be the right place to do this, it is part of the logic of the app, not in the controller (in this case, an interface to load the model). All the operations in the service layer should be transactional.
i.e.: Move this line to the TopicService.findTopicByID method:

Collection<Comment> commentList = topicById.getComments();


2. **Use 'eager' instead of 'lazy'**. Now you are not using 'lazy' .. it is not a real solution, if you want to use lazy, works like a temporary (very temporary) workaround.
3. **use @Transactional in the Controller**. It should not be used here, you are mixing service layer with presentation, it is not a good design.
4. **use OpenSessionInViewFilter**, many disadvantages reported, possible instability.

**In general, the best solution is the 1.**

Reply

#14
From my experience, I have the following methods to solved the famous LazyInitializationException:

**(1) Use Hibernate.initialize**

Hibernate.initialize(topics.getComments());


**(2) Use JOIN FETCH**

You can use the JOIN FETCH syntax in your JPQL to explicitly fetch the child collection out. This is some how like EAGER fetching.



**(3) Use OpenSessionInViewFilter**

LazyInitializationException often occur in view layer. If you use Spring framework, you can use OpenSessionInViewFilter. However, I do not suggest you to do so. It may leads to performance issue if not use correctly.


Reply

#15
The reason is that when you use lazy load, the session is closed.

There are two solutions.

1. Don't use lazy load.

Set `lazy=false` in XML or Set `@OneToMany(fetch = FetchType.EAGER)` In annotation.

2. Use lazy load.

Set `lazy=true` in XML or Set `@OneToMany(fetch = FetchType.LAZY)` In annotation.

and add `OpenSessionInViewFilter filter` in your `web.xml`


Detail See my [POST][1].


[1]:

[To see links please register here]

Reply

#16
your list is lazy loading, so the list wasn't loaded.
call to get on the list is not enough.
use in Hibernate.initialize in order to init the list.
If dosnt work run on the list element and call Hibernate.initialize for each .
this need to be before you return from the transaction scope.
look at [this][1] post.
search for -

Node n = // .. get the node
Hibernate.initialize(n); // initializes 'parent' similar to getParent.
Hibernate.initialize(n.getChildren()); // pass the lazy collection into the session


[1]:

[To see links please register here]

Reply

#17
The reason is you are trying to get the commentList on your controller after closing the session inside the service.

topicById.getComments();

Above will load the commentList only if your hibernate session is active, which I guess you closed in your service.

**So, you have to get the commentList before closing the session.**
Reply

#18
@Controller
@RequestMapping(value = "/topic")
@Transactional
i solve this problem by adding `@Transactional`,i think this can make session open
Reply

#19
The collection `comments` in your model class `Topic` is lazily loaded, which is the default behaviour if you don't annotate it with `fetch = FetchType.EAGER` specifically.

It is mostly likely that your `findTopicByID` service is using a stateless Hibernate session. [A stateless session][1] does not have the first level cache, i.e., no persistence context. Later on when you try to iterate `comments`, Hibernate will throw an exception.

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: mvc3.model.Topic.comments, no session or session was closed

The solution can be:

1. Annotate `comments` with `fetch = FetchType.EAGER`

@OneToMany(fetch = FetchType.EAGER, mappedBy = "topic", cascade = CascadeType.ALL)
private Collection<Comment> comments = new LinkedHashSet<Comment>();

2. If you still would like comments to be lazily loaded, use [Hibernate's stateful sessions][2], so that you'll be able to fetch comments later on demand.


[1]:

[To see links please register here]

[2]:

[To see links please register here]

Reply

#20
Hi All posting quite late hope it helps others,
Thanking in advance to @GMK for this post [Hibernate.initialize(object)][1]


[1]:

[To see links please register here]


when Lazy="true"

Set<myObject> set=null;
hibernateSession.open
set=hibernateSession.getMyObjects();
hibernateSession.close();

now if i access 'set' after closing session it throws exception.

My solution :

Set<myObject> set=new HashSet<myObject>();
hibernateSession.open
set.addAll(hibernateSession.getMyObjects());
hibernateSession.close();

now i can access 'set' even after closing Hibernate Session.
Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through