26

I've got a Hibernate object which's properties are all loaded lazy. Most of these properties are other Hibernate objects or PersistentSets.

Now I want to force Hibernate to eager load these properties for just one time.

Of course I could "touch" each of these properties with object.getSite().size() but maybe there's another way to achieve my goal.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121

8 Answers8

23

This is an old question, but I also wanted to point out the static method Hibernate.initialize.

Example usage:

Person p = sess.createCriteria(Person.class, id);
Hibernate.initialize(p.getChildren());

The children are now initialized to be used even after the session is closed.

Willi Mentzel
  • 27,862
  • 20
  • 113
  • 121
stephen.hanson
  • 9,014
  • 2
  • 47
  • 53
7

The documentation puts it like this:

You can force the usual eager fetching of properties using fetch all properties in HQL.

References

Pascal Thivent
  • 562,542
  • 136
  • 1,062
  • 1,124
3

Dozer works well for this type of thing - you can ask Dozer to map the object to another instance of the same class, and Dozer will visit all objects reachable from the current object.

See this answer to a similar question and my answer to another related question for more details.

Community
  • 1
  • 1
matt b
  • 138,234
  • 66
  • 282
  • 345
1

For me this works:

Person p = (Parent) sess.get(Person.class, id);
Hibernate.initialize(p.getChildren());

Rather than this:

Person p = sess.createCriteria(Person.class, id);
Hibernate.initialize(p.getChildren());
DontVoteMeDown
  • 21,122
  • 10
  • 69
  • 105
oomer
  • 11
  • 1
1

3 ways

1.HQL with left join children

2.SetFetchMode after createCriteria

3.Hibernate.initialize

user3073309
  • 184
  • 2
  • 5
0

This is slow, because it makes a round trip for every item it needs to initialize, but it gets the job done.

private void RecursiveInitialize(object o,IList completed)
{
    if (completed == null) throw new ArgumentNullException("completed");

    if (o == null) return;            

    if (completed.Contains(o)) return;            

    NHibernateUtil.Initialize(o);

    completed.Add(o);

    var type = NHibernateUtil.GetClass(o);

    if (type.IsSealed) return;

    foreach (var prop in type.GetProperties())
    {
        if (prop.PropertyType.IsArray)
        {
            var result = prop.GetValue(o, null) as IEnumerable;
            if (result == null) return;
            foreach (var item in result)
            {
                RecursiveInitialize(item, completed);
            }
        }
        else if (prop.PropertyType.GetGenericArguments().Length > 0)
        {
            var result = prop.GetValue(o, null) as IEnumerable;
            if (result == null) return;
            foreach (var item in result)
            {
                RecursiveInitialize(item, completed);
            }
        }
        else
        {
            var value = prop.GetValue(o, null);
            RecursiveInitialize(value, completed);
        }
    }
}
0

A decade has passed since this question was asked, but I bumped into this problem as well. I noticed that if you are using Spring, annotating the method with org.springframework.transaction.annotation.Transactional solves it nicely.

Example

public void doThing(int id) {
 Thing thing = loadThing(id);
 Stuff stuff = thing.getLazyLoadedStuff();
}

doesn't work, exception thrown. But

@Transactional
public void doThing(int id) {
 Thing thing = loadThing(id);
 Stuff stuff = thing.getLazyLoadedStuff();
}

works.

Lars Andren
  • 8,601
  • 7
  • 41
  • 56
-1

According to the hibernate docs, you should be able to disable lazy property loading by setting the lazy attribute on your particular property mappings:

<class name="Document">
  <id name="id">
    <generator class="native"/>
  </id>
  <property length="50" name="name" not-null="true"/>
  <property lazy="false" length="200" name="summary" not-null="true"/>
  <property lazy="false" length="2000" name="text" not-null="true"/>
</class>
dogbane
  • 266,786
  • 75
  • 396
  • 414
  • 4
    I dont wan't to change the configuration, which is set lazy. I just want to achieve eager loading for one instance. –  Oct 14 '10 at 11:44