问题
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.
回答1:
The documentation puts it like this:
You can force the usual eager fetching of properties using
fetch all properties
in HQL.
References
- Hibernate Core Reference Guide
- 19.1.7. Using lazy property fetching
回答2:
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.
回答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.
回答4:
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());
回答5:
3 ways
1.HQL with left join children
2.SetFetchMode after createCriteria
3.Hibernate.initialize
回答6:
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);
}
}
}
回答7:
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>
来源:https://stackoverflow.com/questions/3932227/force-eager-loading-of-otherwise-lazy-loaded-properties