什么是Hibernate中的延迟加载?

问题描述 投票:162回答:14

什么是Java中的延迟加载?我不明白这个过程。任何人都可以帮我理解延迟加载的过程吗?

java hibernate orm lazy-loading
14个回答
256
投票

假设您有父母,并且该父母有一个孩子的集合。 Hibernate现在可以“延迟加载”子进程,这意味着它在加载父进程时实际上并没有加载所有子进程。相反,它会在请求时加载它们。你可以明确地请求它,或者这更常见,当你试图访问一个孩子时,hibernate会自动加载它们。

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

还要注意n + 1问题。当您访问集合时,Hibernate实际上不会加载所有子节点。相反,它将单独加载每个孩子。迭代集合时,会导致查询每个子集。为了避免这种情况,你可以欺骗hibernate同时加载所有孩子,例如通过调用parent.getChildren()。size()。


0
投票

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

lazy =“false”默认情况下加载初始化提到的唯一的孩子是lazy.in的情况是父的是加载不支持孩子


0
投票

延迟设置决定是否在加载父对象时加载子对象。你需要这样设置父类的相应hibernate映射文件.Lazy = true(表示不加载子)默认情况下,子对象的延迟加载为true 。


0
投票

好吧,它只是意味着加载您当前需要的数据,而不是一次性加载大量数据,而您现在不会使用它们。从而使应用程序加载时间比平时快。


0
投票

令人惊讶的是,没有一个答案谈论如何通过屏幕后面的hibernate实现它。

Lazy loading是一种设计模式,由于性能原因而在休眠中有效地使用,涉及以下技术。


1.字节码检测:

使用hibernate hooks增强基类定义,以拦截对该实体对象的所有调用。

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

1.1编译时间

  • 后编译时操作
  • 主要是通过maven / ant插件

1.2运行时间

  • 如果没有完成编译时间检测,则在运行时创建使用javassist之类的库

2. Proxies

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

另见:Javassist. What is the main idea and where real use?


0
投票

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

使用EAGER加载时,您可以定义一个在查询时无法覆盖的全局提取计划,这意味着您只能在设计实体模型时做出决策。 EAGER fetching is a code smell,因为获取策略是一个查询时策略,它可能与业务用例不同。

fetching strategy是一个非常重要的方面,因为过多的EAGER提取会导致严重的性能相关问题。


70
投票

“延迟加载”表示只有在您第一次实际访问实体时才会加载实体。

pattern是这样的:

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

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

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

EG

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

24
投票

Martin Fowler定义了Lazy Load中的Patterns of Enterprise Application Architecture模式:

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

因此,在加载给定对象时,我们的想法是不要急于加载您可能不会立即使用的相关对象来保存相关的性能成本。相反,只有在使用时才会加载相关对象。

这不是特定于数据访问和Hibernate的模式,但它在这些字段中特别有用,并且Hibernate支持一对多关联和一点关联(一对一和多对一)的延迟加载在一定条件下。在Hibernate 3.0参考文档的Chapter 19中更详细地讨论了惰性交互。


15
投票

默认延迟加载是真的。延迟加载意味着当执行选择查询时它不会命中数据库。它将等待getter函数,即当我们需要时,它将从数据库中获取。例如:你是一个有很多玩具的孩子的父母。但是当前的问题是每当你打电话给他时(我们假设你有一个男孩),他也带着他所有的玩具来找你。现在这是一个问题,因为你不希望他一直带着他的玩具。因此,作为理性的父母,你要向前走,并将孩子的玩具定义为LAZY。现在每当你打电话给他时,他就会在没有玩具的情况下来找你。


11
投票

延迟提取决定在加载父对象时是否加载子对象。您需要这样设置父类的相应hibernate映射文件。 Lazy = true(表示不加载子)默认情况下,子对象的延迟加载为true。

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

但在某些情况下,您需要在加载父项时加载子对象。只需使lazy = false,hibernate将在从数据库加载父级时加载子级。

示例:如果您有一个TABLE? EMPLOYEE映射到Employee对象并包含一组Address对象。父类:Employee类,子类:地址类

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": - 这是默认配置。如果你不提,那么hibernate认为lazy = true。当您加载Employee对象时,未加载时间子对象Adress。您需要额外调用数据库才能获取地址对象。如果你调用employee.getAdress()那么那个时间数据库查询将触发并返回结果。新鲜数据库调用。


8
投票

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


8
投票

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

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


3
投票

延迟设置决定是否在加载父对象时加载子对象。你需要这样设置父类的相应hibernate映射文件.Lazy = true(表示不加载子)默认情况下,子对象的延迟加载为true 。这确保不加载子对象,除非通过在parent上调用getChild()方法在应用程序中显式调用它们。在这种情况下,当在Parent上执行getChild()时,hibernate会发出一个新的数据库调用来加载子对象。 object。但在某些情况下,您需要在加载父对象时加载子对象。只需使lazy = false并且hibernate将在从数据库加载父项时加载子项.Exampleslazy = true(默认)如果不经常需要,则可以使User类的地址子项变为惰性.lazy = false但是您可能需要加载每当您处理在线书店的书籍时,Book父级的Author对象。


2
投票

延迟加载是计算机编程中常用的设计模式,用于将对象的初始化推迟到需要它的点。如果正确和适当地使用它,它可以有助于程序操作的效率

维基百科

来自hibernate.org的Lazy Loading的链接

© www.soinside.com 2019 - 2024. All rights reserved.