我有一个 Hibernate 对象,它的属性都是惰性加载的。这些属性中的大多数是其他 Hibernate 对象或 PersistentSet。
现在我想强制 Hibernate 一次性加载这些属性。
当然,我可以“触摸”这些属性中的每一个,object.getSite().size()
但也许还有另一种方法可以实现我的目标。
我有一个 Hibernate 对象,它的属性都是惰性加载的。这些属性中的大多数是其他 Hibernate 对象或 PersistentSet。
现在我想强制 Hibernate 一次性加载这些属性。
当然,我可以“触摸”这些属性中的每一个,object.getSite().size()
但也许还有另一种方法可以实现我的目标。
这是一个老问题,但我也想指出静态方法Hibernate.initialize
。
示例用法:
Person p = sess.createCriteria(Person.class, id);
Hibernate.initialize(p.getChildren());
现在,即使在会话关闭后也可以使用子级。
对我来说,这有效:
Person p = (Parent) sess.get(Person.class, id);
Hibernate.initialize(p.getChildren());
而不是这样:
Person p = sess.createCriteria(Person.class, id);
Hibernate.initialize(p.getChildren());
3种方式
1.带有左连接子项的HQL
2.createCriteria后的SetFetchMode
3.休眠.初始化
这很慢,因为它对需要初始化的每个项目进行往返,但它完成了工作。
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);
}
}
}
根据休眠文档,您应该能够通过lazy
在特定属性映射上设置属性来禁用延迟属性加载:
<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>