How to Solve the "Failed to Lazily Initialize a Collection of Role" Hibernate Exception

How to solve the “failed to lazily initialize a collection of role” Hibernate exception

If you know that you'll want to see all Comments every time you retrieve a Topic then change your field mapping for comments to:

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

Collections are lazy-loaded by default, take a look at this if you want to know more.

How to fix Hibernate LazyInitializationException: failed to lazily initialize a collection of roles, could not initialize proxy - no Session

You need to either add fetch=FetchType.EAGER inside your ManyToMany annotations to automatically pull back child entities:

@ManyToMany(fetch = FetchType.EAGER)

A better option would be to implement a spring transactionManager by adding the following to your spring configuration file:

<bean id="transactionManager"
class="org.springframework.orm.hibernate4.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<tx:annotation-driven />

You can then add an @Transactional annotation to your authenticate method like so:

@Transactional
public Authentication authenticate(Authentication authentication)

This will then start a db transaction for the duration of the authenticate method allowing any lazy collection to be retrieved from the db as and when you try to use them.

Failed to lazily initialize a collection of role with SpringBoot

Please read one of my articles carefully: https://arnoldgalovics.com/lazyinitializationexception-demystified/

Your main problem is that you are trying to access an entity reference outside of a transaction.
You have multiple options here:

  • Fetch the necessary data within the same logical transaction
  • Use FETCH JOIN in your JPQL query
  • Use projections

More reading about projections: https://arnoldgalovics.com/using-projections-in-your-data-access-layer/

Also, consider the performance impact of using projections: https://arnoldgalovics.com/how-much-projections-can-help/

Hibernate failed to lazily initialize a collection of role could not initialize proxy - no Session

There are various options:

  1. Call a method on the mapped relation
  2. Fetch Join in JPQL
  3. Fetch Join in Criteria API
  4. Named Entity Graph
  5. Dynamic Entity Graph

For details please read:
https://thorben-janssen.com/5-ways-to-initialize-lazy-relations-and-when-to-use-them/

failed to lazily initialize a collection of role: myapp.myapp.models.Contact.messages, could not initialize proxy - no Session

You can lazy-load only within transaction context.
Use @Transactional annotation on your service class:

@Service
@Transactional
public class Service {
public void serviceClass(long id) {
Contact contact = contactRepository.findOne(id);
Messages msg = new Messages();
msg.setContact(contact);

// do some work here

Messages savedMessage = messagesRepository.save(msg);
contact.addMessage(savedMessage);
contactRepository.save(contact);
}
}

Hibernate: LazyInitializationException: failed to lazily initialize a collection of role. Could not initialize proxy - no Session

It seems that model is a detached entity.

Try to merge and perform operations on a merge instance:

@Override
public void process(Model model) {
...
Model mergedModel = session.merge(model);

mergedModel.addEntity(createEntity());
...
}

Hibernate "failed to lazily initialize a collection" runtime error

I worked with this SO thread even before I posted my question:

How to solve the “failed to lazily initialize a collection of role” Hibernate exception

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

Possible solutions:

  • 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...

  • 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.

  • use @Transactional in the Controller. It should not be used here, you
    are mixing service layer with presentation, it is not a good design.

  • use OpenSessionInViewFilter, many disadvantages reported, possible
    instability.

Unfortunately, @Transactional and and OpenSessionInView weren't available in my scenario. FetchType.EAGER wasn't an option. And "doing everything inside the session" was exactly the problem I was trying to resolve.

Another excellent response, from the same thread:

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

  • Use Hibernate.initialize

    Hibernate.initialize(topics.getComments());

  • 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.

  • Use OpenSessionInViewFilter

What I learned:

  • List<Contact> contacts = session.createQuery("FROM Contact").list();: only returns the "parent" (Contact) record, none of the child (Notes) records.

    WORKAROUND: Explicitly read each of the child notes while the session is still active. This triggers a second "select", and fetches the child data.

  • List<Contact> contacts = session.createQuery("SELECT c FROM Contact c INNER JOIN FETCH c.notes").list();: doesn't return any Contacts with 0 child Notes.

    WORKAROUND: Change the code to ensure that every contact has at least one note (by automatically creating a note when a Contact is created). "Join fetch" only makes one SQL call.

Anyway - I got it working.

"failed to lazily initialize a collection of role"

It was a surprise to know that my error wasnt in the controllers, but in the hbm.xml of the files Post, Comment and Fbuser.
In those files, I have these lines in various ways:

<many-to-one name="fbuser" class="pojos.Fbuser" lazy="false" fetch="select">
<column name="fbuser_id" not-null="true" />
</many-to-one>
<property name="info" type="string">
<column name="info" length="300" not-null="true" />
</property>
<property name="plikes" type="int">
<column name="plikes" not-null="true" />
</property>
<set name="comments" table="comment" inverse="true" lazy="false" fetch="select">
<key>
<column name="post_id" not-null="true" />
</key>
<one-to-many class="pojos.Comment" />
</set>

The problem came when I didnt added the attribute lazy="false" in the sets and many-to-one/one-to-many tags!



Related Topics



Leave a reply



Submit