Hibernate中的延迟加载是什么?


178

Java中的延迟加载是什么?我不明白这个过程。有人可以帮助我了解延迟加载的过程吗?

Answers:


268

假设您有一个父母,而那个父母有很多孩子。Hibernate现在可以“延迟加载”子级,这意味着它在加载父级时实际上并没有加载所有子级。而是在要求时加载它们。您可以显式地请求此请求,或者(更常见的是),当您尝试访问孩子时,hibernate会自动加载它们。

延迟加载可以帮助显着提高性能,因为通常不需要子级,因此不会加载它们。

还要提防n + 1问题。当您访问集合时,Hibernate实际上不会加载所有子代。相反,它将单独加载每个孩子。遍历集合时,这将导致每个孩子的查询。为了避免这种情况,您可以诱使休眠模式同时加载所有子级,例如,通过调用parent.getChildren()。size()。


5
另外,应该使用Hibernate.initialize(parent.getChildren())
HakunaMatata

18
实际上,“当您访问集合时...将单独加载每个子项”这样的语句实际上是不准确的。它实际上恰好相反。对parent.getChildren()的任何取消引用都将导致Hibernate在一个数据库查询中加载集合中的所有子项。除非您使用了非常特殊的“额外延迟”延迟加载提示。或者,除非您将集合缓存在第二级缓存中,并且关联的子项也不会被缓存。
史蒂夫·埃伯索尔

噢,堆栈溢出-最好的答案是在页面底部;-)
Piotrek Hryciuk

76

“延迟加载”是指当您一次实际访问实体时,才会加载实体。

模式是这样的:

public Entity getEntity() {
    if (entity == null) {
        entity = loadEntity();
    }
    return entity;
}

这样可以节省预先在大型数据集中预加载/预填充所有实体的成本,而实际上您根本不需要所有实体。

在Hibernate中,您可以配置为延迟加载子实体的集合。在实际的延迟加载,然后在方法内部完成PersistentSet这Hibernate使用的“罩下的”指定实体的集合Set

例如

public class Parent {
    private Set<Child> children;

    public Set<Child> getChildren() {
        return children;
    }
}

public void doSomething() {
    Set<Child> children = parent.getChildren(); // Still contains nothing.

    // Whenever you call one of the following (indirectly), 
    // Hibernate will start to actually load and fill the set.
    children.size();
    children.iterator();
}

25

Martin Fowler 在企业应用程序体系结构模式中定义了惰性加载模式,如下所示:

一个不包含您需要的所有数据但知道如何获取它的对象。

因此,在加载给定对象时,其想法是不要急于加载您可能不会立即使用的相关对象以节省相关性能成本。而是仅在使用时加载相关对象。

这不是特定于数据访问和Hibernate的模式,但是在此类领域中特别有用,并且Hibernate还支持延迟加载一对多关联和单点关联(一对一和多对一)。在某些条件下。Hibernate 3.0参考文档的第19章将更详细地讨论惰性交互。


15

默认情况下,延迟加载为true。延迟加载是指执行选择查询时,它将不会访问数据库。它将等待getter函数,即当我们需要时,它将从datbase中获取。例如:您是一个有很多玩具的孩子的父母。但是当前的问题是,只要您打电话给他(我们假设您有一个男孩),他也会带着所有玩具来找您。现在这是一个问题,因为您不希望他一直都随身携带玩具。因此,作为理论上的父母,您会继续前进,并将孩子的玩具定义为LAZY。现在,每当您打电话给他时,他都会带着他的玩具来到您身边。


11

延迟获取决定在加载父对象时是否加载子对象。您需要这样做来设置父类各自的休眠映射文件。 Lazy = true(意味着不加载子对象)默认情况下,子对象的延迟加载为true。

这样可以确保不加载子对象,除非在应用程序中通过调用getChild()parent的方法显式调用了子对象。在这种情况下,hibernate会发出一个新的数据库调用,以getChild()在对Parent对象进行实际调用时加载子对象。

但是在某些情况下,确实需要在加载父对象时加载子对象。只需设置lazy = false,当从数据库中加载父对象时,休眠将加载子对象。

示例:如果您有TABLE?EMPLOYEE映射到Employee对象,并包含一组Address对象。上级:雇员级,下级:地址级

public class Employee { 
private Set address = new HashSet(); // contains set of child Address objects 
public Set getAddress () { 
return address; 
} 
public void setAddresss(Set address) { 
this. address = address; 
} 
} 

在Employee.hbm.xml文件中

<set name="address" inverse="true" cascade="delete" lazy="false"> 
<key column="a_id" /> 
<one-to-many class="beans Address"/> 
</set> 

在以上配置中。如果lazy="false":-在加载Employee对象时,该时间子对象Address也将被加载并设置为setAddresss()方法。如果调用employee.getAdress(),则返回加载的数据。没有新的数据库调用。

如果lazy="true":-这是默认配置。如果您不提及,则休眠时请考虑lazy = true。当您加载Employee对象时,该时间子对象Adress不会被加载。您需要对数据库进行额外的调用才能获取地址对象。如果您致电,employee.getAdress()则该时间数据库查询将触发并返回结果。新的数据库调用。


在这种情况下,员工和地址没有父子关系。这是“有”的关系
2015年

这是聚合而不是继承。
Rishi

11

用外行的语言来说,就像您正在做蛋糕一样,您需要从冰箱中取出5-10种食材。您有两种选择,一种是从冰箱中取出所有食材,然后将其放在厨房平台上,或者在需要时携带所需的物品。

同样,在热切加载中,您获取有关Bean及其相关类的所有信息(不是子关系或is-a关系,但是有关系,即蛋糕有面粉,牛奶,奶油等),并且在延迟加载的情况下,首先您只需携带来自同一表的标识符和值(如果是蛋糕,首先需要在碗中添加必需的成分)。来自其他表的所有信息将在需要/使用时获取。


8

延迟加载?好吧,这只是意味着子记录不会立即获取,而是在您尝试访问它们时自动获取。


3

延迟设置决定是否在加载父对象时加载子对象,需要设置父类各自的休眠映射文件。lazy = true(表示不加载子对象)默认情况下,子对象的延迟加载为true 。这样可以确保不加载子对象,除非通过在父对象上调用getChild()方法在应用程序中显式调用了子对象。在这种情况下,当在父对象上实际调用getChild()时,hibernate发出一个新的数据库调用来加载子对象对象。但是在某些情况下,确实需要在加载父对象时加载子对象。只需将lazy = false设置为false,当从数据库中加载父级时,休眠将加载子级。示例lazy = true(默认值)如果不需要经常使用,则可以将User类的地址子级设置为惰性。


3

延迟加载允许您推迟关联检索或更好地控制获取策略。

使用EAGER加载时,您将定义一个全局获取计划,该计划无法在查询时被覆盖,这意味着您仅限于在设计实体模型时做出的决定。该EAGER抓取是一个代码味道,因为抓取策略是查询时策略,它可能从一个业务用例的不同而异。

抓取策略是一个非常重要的方面,因为太多EAGER取会导致严重的性能相关的问题。


2

延迟加载是一种设计模式,通常在计算机编程中用于将对象的初始化推迟到需要它的时间点。如果使用得当,可以提高程序的运行效率。

维基百科

来自hibernate.org 的延迟加载链接


1

好吧,这只是意味着加载当前需要的数据,而不是立即加载现在不使用的全部数据。从而使应用程序加载时间比平时更快。


0

Hiberante支持对实体和集合进行延迟初始化的功能。Hibernate引擎仅加载我们要查询的对象,而不会加载其他实体或集合。

默认情况下,lazy =“ false”加载唯一子对象的初始化提及是lazy。情况,如果为true,则父对象正在加载,不支持child


0

延迟设置决定是否在加载父对象时加载子对象,需要设置父类各自的休眠映射文件。lazy = true(表示不加载子对象)默认情况下,子对象的延迟加载为true 。


0

令人惊讶的是,没有任何答案谈论在屏幕后休眠的方式是如何实现的。

延迟加载是一种设计模式,出于性能原因,该模式可有效地用于休眠模式,其中涉及以下技术。


1.字节码检测

使用休眠挂钩增强了基类定义,以拦截对该实体对象的所有调用。

在编译时或运行[加载]时完成

1.1 编译时间

  • 编译后操作

  • 主要由maven / ant插件提供

1.2 运行时间

2.代理

Hibernate返回的实体对象是实型的代理。

另请参阅: Javassist。主要思想是什么,实际用途是什么?

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.