强制预先加载原本延迟加载的属性

发布于 2024-09-27 02:53:23 字数 181 浏览 4 评论 0原文

我有一个 Hibernate 对象,它的属性都是惰性加载的。大多数这些属性是其他 Hibernate 对象或 PersistentSet。

现在我想强制 Hibernate 一次性加载这些属性。

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

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

攒一口袋星星 2024-10-04 02:53:23

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

用法示例:

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

即使在会话关闭后,子级现在也已初始化为可以使用。

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.

稍尽春風 2024-10-04 02:53:23

文档是这样描述的:

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

参考资料

The documentation puts it like this:

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

References

行至春深 2024-10-04 02:53:23

Dozer 非常适合这种类型的事情 - 您可以要求 Dozer 将对象映射到同一对象的另一个实例类,Dozer 将访问当前对象可到达的所有对象。

请参阅类似问题的答案我对另一个相关问题的回答了解更多详细信息。

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.

左岸枫 2024-10-04 02:53:23

对我来说这有效:

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

而不是这样:

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

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());
尹雨沫 2024-10-04 02:53:23

3种方式

1.带有左连接子级的

HQL 2.createCriteria之后的SetFetchMode

3.Hibernate.initialize

3 ways

1.HQL with left join children

2.SetFetchMode after createCriteria

3.Hibernate.initialize

妞丶爷亲个 2024-10-04 02:53:23

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

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

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);
        }
    }
}
拥有 2024-10-04 02:53:23

自从提出这个问题以来已经过去了十年,但我也遇到了这个问题。我注意到,如果您使用 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();
}

有效。

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.

土豪我们做朋友吧 2024-10-04 02:53:23

根据 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>

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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文