什么时候在hibernate中使用Lazy loading / Eager加载?

时间:2012-09-24 16:47:00

标签: java hibernate lazy-loading

我相信只有两种使用Hibernate加载对象的方法,即延迟加载,一种是急切加载。延迟加载有其自身的优点,它不会加载大量对象,而只是在您需要它们时。我还了解到,如果你想强制加载一个对象的所有子项,你可以简单地调用parent.getChildren().size()。所以我们假设我们有以下对象

@Entity
public class Customer{
public Set<Order> order;
}

@Entity
public class Order{
}

让我们假设我们的客户在我们的系统中有订单,而且可能不止一个甚至是空。所以我的问题是在这种情况下总是使用急切加载不是更好吗?我们需要与客户相关的订单的大小或一些信息。在这种情况下使用延迟加载有什么好处,有什么好处吗?

我试图了解在何处使用延迟加载以及在何处使用预先加载,非常感谢您的洞察力。

3 个答案:

答案 0 :(得分:20)

  

我试图了解在何处使用延迟加载以及在何处使用   渴望加载,非常感谢您的洞察力。

以下是一些想法:

1)如果你要总是使用某些东西(肯定),你可以急于加载它 2)与1相关,如果你几乎不会使用某些东西,懒得加载它 3)当涉及大型集合时,延迟加载往往更有用 4)急切地加载东西会减少会话相关的错误,而且可能会降低性能 5)对于复杂的数据模型和/或大型数据库,您将看到您的应用程序在加载调整策略时的工作方式 6)第一次很难做到正确。做正确的事情,如果有必要,不要害怕改变 7)对于大型数据集,你可能最终会编写自定义的hql /查询,其中默认映射可以被覆盖,所以lazy vs eager不会那么重要。

如果你相信#6,那么不要试图计划太远,并且如果你不得不改变它。

WRT你的具体例子,我可能会写一堆查询来访问数据(当然是由适当的业务需求驱动)

1)一个加载客户的查询,并将订单留在db中(如此延迟加载),当我需要获取客户信息时,我会调用该订单 2)在我需要的情况下加载客户和所有订单信息的查询。所以这种情况我会忽略默认映射。

有了这两个查询,在我的服务层中,我有了根据情境的上下文所需的工具。

答案 1 :(得分:5)

link完全回答了你的问题。

LAZY加载用于相关实体大小巨大且另一方面不需要每次都取出的情况

EAGER应该与正确的分析一起使用,因为它会在每次加载主实体时加载关系。

因此,如果关系对于业务逻辑计算是绝对必要的,那么您应该考虑使用EAGER加载; LAZY装载将服务于大多数情况并且提供较少的性能问题。

答案 2 :(得分:2)

LAZY是所有Hibernate批注关系的默认访存类型。当您使用Lazy访存类型时,Hibernate不会加载该特定对象实例的关系。那么,Eager和Lazy有什么区别?

获取类型Eager本质上与Lazy相反,Eager默认情况下将加载与由Hibernate加载的特定对象相关的所有关系。这意味着如果您将关系更改为此

enter image description here

Hibernate现在将默认情况下将用户配置文件加载到用户对象中。这意味着,如果您访问user.getUserProfile(),它将不会为NULL(除非联接表实际上不包含“ user_profile_id”联接列中的匹配行)。

因此,长话短说:

FetchType.LAZY =除非通过getter明确“要求”,否则不会加载关系 FetchType.EAGER =加载所有关系。

利弊 如果使用延迟加载方法会导致NullPointerExceptions,那么为什么要使用它呢?好吧,让我们花一点时间考虑一下。

假设我们有一个与其他对象有10种不同关系的User对象。假设您有一个正在尝试登录的用户,而您只想检查其用户名和密码是否正确,并且与数据库中存储的用户名和密码匹配。您是否真的要加载所有10个关系,而不使用那些已加载的关系中的任何一个?记住,就将所有信息加载到Java对象并将它们保存在内存中所花费的时间而言,从数据库加载东西是相当“昂贵”的。如果这些关系之一指向一个对象,且该对象还具有10个关系(并且所有这些关系都设置为访存类型EAGER),会发生什么。想想从数据库加载到内存中的对象的大屠杀!

我喜欢的表达方式是这样的:

EAGER:方便,但是很慢

LAZY:编码更多,但效率更高