我有一个 Hibernate 对象,其所有属性都是懒加载。其中大部分属性都是其他 Hibernate 对象或 PersistentSets。
现在,我想强制 Hibernate 仅一次地急切加载这些属性。
当然,我可以使用 object.getSite().size()
触发每个属性,但也许还有另一种方法来实现我的目标。
我有一个 Hibernate 对象,其所有属性都是懒加载。其中大部分属性都是其他 Hibernate 对象或 PersistentSets。
现在,我想强制 Hibernate 仅一次地急切加载这些属性。
当然,我可以使用 object.getSite().size()
触发每个属性,但也许还有另一种方法来实现我的目标。
这是一个旧问题,但我也想指出静态方法Hibernate.initialize
。
使用示例:
Person p = sess.createCriteria(Person.class, id);
Hibernate.initialize(p.getChildren());
即使会话关闭后,这些子项现在也可以被初始化并使用。
Dozer 对于这种类型的操作很有效 - 你可以要求 Dozer 把对象映射到同一类的另一个实例中,Dozer 将访问从当前对象可达的所有对象。
更多细节请参见类似问题的这个答案和我对另一个相关问题的回答。
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.Hibernate.initialize
已经过去十年了,但我也遇到了这个问题。我注意到,如果你正在使用Spring,在方法上使用org.springframework.transaction.annotation.Transactional
注解可以很好地解决它。
示例
public void doThing(int id) {
Thing thing = loadThing(id);
Stuff stuff = thing.getLazyLoadedStuff();
}
不起作用,抛出异常。但是
@Transactional
public void doThing(int id) {
Thing thing = loadThing(id);
Stuff stuff = thing.getLazyLoadedStuff();
}
正常工作。
这很慢,因为它需要为每个需要初始化的项目进行一次往返,但它完成了工作。
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>