Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I access lazy-loaded fields after the session has closed, using hibernate?

consider this scenario:

  • I have loaded a Parent entity through hibernate
  • Parent contains a collection of Children which is large and lazy loaded
  • The hibernate session is closed after this initial load while the user views the Parent data
  • The user may choose to view the contents of the lazy Children collection
  • I now wish to load that collection

What are the ways / best way of loading this collection?

  • Assume session-in-view is not an option as the fetching of the Children collection would only happen after the user has viewed the Parent and decided to view the Children.
  • This is a service which will be accessed remotely by web and desktop based client.

Thanks.

like image 212
Paul Adamson Avatar asked Jul 01 '09 14:07

Paul Adamson


People also ask

How does lazy loading works in Hibernate How will load a lazily loaded items in Hibernate to avoid lazy load exception?

7. Lazy Loading in Hibernate. Hibernate applies lazy loading approach on entities and associations by providing a proxy implementation of classes. Hibernate intercepts calls to an entity by substituting it with a proxy derived from an entity's class.

Which method uses lazy loading in the Hibernate session?

ManyToOne and OneToOne associations used lazy loading strategy by default.

Can you explain lazy loading in Hibernate?

Lazy loading in Hibernate means fetching and loading the data, only when it is needed, from a persistent storage like a database. Lazy loading improves the performance of data fetching and significantly reduces the memory footprint.

How Hibernate handle lazy initialization exception?

The right way to fix a LazyInitializationException is to fetch all required associations within your service layer. The best option for that is to load the entity with all required associations in one query.


2 Answers

The lazy collection can be loaded by using Hibernate.initialize(parent.getCollection()) except that the parent object needs to be attached to an active session.

This solution takes the parent Entity and the name of the lazy-loaded field and returns the Entity with the collection fully loaded.

Unfortunately, as the parent needs to be reattached to the newly opened session, I can't use a reference to the lazy collection as this would reference the detached version of the Entity; hence the fieldName and the reflection. For the same reason, this has to return the attached parent Entity.

So in the OP scenario, this call can be made when the user chooses to view the lazy collection:

Parent parentWithChildren = dao.initialize(parent,"lazyCollectionName");

The Method:

public Entity initialize(Entity detachedParent,String fieldName) {
    // ...open a hibernate session...
    // reattaches parent to session
    Entity reattachedParent = (Entity) session.merge(detachedParent); 

    // get the field from the entity and initialize it
    Field fieldToInitialize = detachedParent.getClass().getDeclaredField(fieldName);
    fieldToInitialize.setAccessible(true);
    Object objectToInitialize = fieldToInitialize.get(reattachedParent);

    Hibernate.initialize(objectToInitialize);
    return reattachedParent;
}
like image 171
Paul Adamson Avatar answered Sep 29 '22 17:09

Paul Adamson


I'm making some assumptions about what the user is looking at, but it seems like you only want to retrieve the children if the user has already viewed the parent and really wants to see the children.

Why not try opening a new session and fetching the children by their parent? Something along the lines of ...

criteria = session.createCriteria(Child.class);
criteria.add(Restrictions.eq("parent", parent));
List<Child> children = criteria.list();
like image 26
zmf Avatar answered Sep 29 '22 16:09

zmf