强制预加载本来是懒加载的属性

26

我有一个 Hibernate 对象,其所有属性都是懒加载。其中大部分属性都是其他 Hibernate 对象或 PersistentSets。

现在,我想强制 Hibernate 仅一次地急切加载这些属性。

当然,我可以使用 object.getSite().size() 触发每个属性,但也许还有另一种方法来实现我的目标。

8个回答

23

这是一个旧问题,但我也想指出静态方法Hibernate.initialize

使用示例:

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

即使会话关闭后,这些子项现在也可以被初始化并使用。


7

文档中是这样描述的:

您可以使用HQL中的fetch all properties来强制进行通常的急切属性获取。

参考资料


3

1
对我来说,这个可以工作:

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

与其这样:

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

1

3种方法

1.使用左连接子查询的HQL

2.在createCriteria之后使用SetFetchMode

3.Hibernate.initialize


0

已经过去十年了,但我也遇到了这个问题。我注意到,如果你正在使用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();
}

正常工作。


0

这很慢,因为它需要为每个需要初始化的项目进行一次往返,但它完成了工作。

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);
        }
    }
}

-1
根据hibernate文档,您应该能够通过在特定属性映射上设置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>

4
我不想改变设置为“懒加载”的配置,我只想对一个实例进行“急加载”。 - user321068

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接