什么是Java中的延迟加载?我不明白这个过程。任何人都可以帮我理解延迟加载的过程吗?
答案 0 :(得分:256)
假设您有父母,并且该父母有一系列儿童。 Hibernate现在可以“延迟加载”子进程,这意味着它在加载父进程时实际上并没有加载所有子进程。相反,它会在请求时加载它们。你可以明确地请求这个,或者这更常见,当你试图访问一个孩子时,hibernate会自动加载它们。
延迟加载有助于显着提高性能,因为通常您不需要孩子,因此不会加载它们。
还要注意n + 1问题。当您访问集合时,Hibernate实际上不会加载所有子节点。相反,它将单独加载每个孩子。迭代集合时,会导致查询每个子集。为了避免这种情况,你可以欺骗hibernate同时加载所有孩子,例如通过调用parent.getChildren()。size()。
答案 1 :(得分:70)
“延迟加载”表示当实际访问第一个时间的实体时,将仅 >
pattern是这样的:
public Entity getEntity() {
if (entity == null) {
entity = loadEntity();
}
return entity;
}
这样可以节省预先加载/预填充所有大型数据集中实体的成本,而您实际上并不需要所有。
在Hibernate中,您可以配置为延迟加载子实体的集合。 实际延迟加载然后在PersistentSet
的方法内完成,Hibernate在“引擎盖下”使用这些方法将实体集合指定为Set
。
E.g。
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();
}
答案 2 :(得分:24)
Martin Fowler在Lazy Load中定义了Patterns of Enterprise Application Architecture模式:
一个对象,它不包含您需要的所有数据,但知道如何获取它。
因此,在加载给定对象时,我们的想法是不要急切加载您可能不会立即使用的相关对象来保存相关的性能成本。相反,只有在使用时才会加载相关对象。
这不是特定于数据访问和Hibernate的模式,但它在这些领域特别有用,而且Hibernate支持一对多关联和单点关联的延迟加载(一对一和多对多关联)一)在某些条件下也是如此。 在Hibernate 3.0参考文档的Chapter 19中更详细地讨论了惰性交互。
答案 3 :(得分:15)
Bydefault延迟加载是真的。延迟加载意味着当执行select查询时它不会命中数据库。它将等待getter函数,即当我们需要时,它将从数据库中获取。 例如: 你是一个有很多玩具的孩子的父母。但是当前的问题是每当你打电话给他时(我们假设你有一个男孩),他也带着他所有的玩具来找你。现在这是一个问题,因为你不希望他一直带着他的玩具。 因此,作为理性的父母,你要向前走,并将孩子的玩具定义为LAZY。现在每当你打电话给他时,他就会在没有玩具的情况下来找你。
答案 4 :(得分:11)
延迟抓取决定在加载父对象时是否加载子对象。
您需要这样设置父类的相应hibernate映射文件。
Lazy = true
(表示不加载孩子)
默认情况下,子对象的延迟加载为true。
这确保除非通过在parent上调用getChild()
方法在应用程序中显式调用子对象,否则不会加载子对象。在这种情况下,hibernate会在{{1}时发出新的数据库调用以加载子对象}在父对象上被调用。
但在某些情况下,您需要在加载父级时加载子对象。 只需使lazy = false,hibernate将在从数据库加载父项时加载子项。
示例: 如果你有一个TABLE? EMPLOYEE映射到Employee对象并包含一组Address对象。 父类:员工类, 子类:地址类
getChild()
在Employee.hbm.xml文件中
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;
}
}
在上面的配置中。
如果<set name="address" inverse="true" cascade="delete" lazy="false">
<key column="a_id" />
<one-to-many class="beans Address"/>
</set>
: - 当您加载Employee对象时,也会加载时间子对象Address并将其设置为setAddresss()方法。
如果你调用employee.getAdress()然后加载数据返回。没有新的数据库调用。
如果lazy="false"
: - 这是默认配置。如果你不提,那么hibernate认为lazy = true。
当您加载Employee对象时,未加载时间子对象Adress。您需要额外调用数据库才能获取地址对象。
如果您调用lazy="true"
,则该时间数据库查询将触发并返回结果。新鲜的数据库电话。
答案 5 :(得分:8)
懒惰加载?好吧,它只是意味着不会立即获取子记录,而是在您尝试访问它们时自动提取。
答案 6 :(得分:8)
用外行的语言来说,就像你正在做蛋糕一样,你需要冰箱里的5-10种食材。您有两种选择,从冰箱中取出所有食材并将其放在厨房平台上,或在需要时带上您想要的食物。
同样,在急切的加载中,你获取有关bean及其相关类的所有信息(不是子或关系,但有关系,即蛋糕有面粉,有牛奶,有奶油等),如果是懒惰加载时,首先只带来来自同一张桌子的标识符和值(必要的成分,如果是蛋糕,首先你需要在碗里)。来自其他表的所有信息将在需要/使用时获取。
答案 7 :(得分:3)
延迟设置决定是否在加载父对象时加载子对象。你需要这样设置父类的相应hibernate映射文件.Lazy = true(表示不加载子)默认情况下,孩子的延迟加载对象是真的。这确保不加载子对象,除非通过在parent上调用getChild()方法在应用程序中显式调用它们。在这种情况下,当在Parent上执行getChild()时,hibernate会发出一个新的数据库调用来加载子对象。 object。但在某些情况下,您需要在加载父对象时加载子对象。只需使lazy = false并且hibernate将在从数据库加载父项时加载子项.Exampleslazy = true(默认)如果不经常需要,则可以使User类的地址子项变为惰性.lazy = false但是您可能需要加载每当您处理在线书店的图书时,Book父级的Author对象。
答案 8 :(得分:2)
答案 9 :(得分:0)
Hiberante支持实体和集合的延迟初始化功能。 Hibernate引擎只加载我们查询的那些对象而不是其他的entites或集合。
lazy =“false”默认情况下加载初始化提到的唯一的孩子是lazy.in的情况是真的是父级正在加载不支持孩子
答案 10 :(得分:0)
延迟设置决定是否在加载父对象时加载子对象。你需要这样设置父类的相应hibernate映射文件.Lazy = true(表示不加载子)默认情况下,孩子的延迟加载对象是真的。
答案 11 :(得分:0)
延迟加载允许您推迟关联检索或更好地控制提取策略。
使用EAGER加载时,您可以定义一个全局获取计划,该计划在查询时无法覆盖,这意味着您只能在设计实体模型时做出决定。 EAGER fetching is a code smell,因为提取策略是一个查询时策略,它可能与业务用例不同。
fetching strategy是一个非常重要的方面,因为过多的EAGER提取会导致与性能相关的严重问题。
答案 12 :(得分:0)
好吧,它只是意味着加载您当前需要的数据,而不是立即加载您现在不会使用的一大堆数据。从而使应用程序加载时间比平时快。
答案 13 :(得分:0)
令人惊讶的是,没有一个答案谈论屏幕后面的hibernate是如何实现的。
Lazy loading 是一种在hibernate中有效使用的设计模式,其性能原因涉及以下技术。
<强> 1。字节代码检测:
使用hibernate hooks增强基类定义,以拦截对该实体对象的所有调用。
在编译时或运行[加载]时间
完成1.1 编译时间
编译后时间操作
主要通过maven / ant plugins
1.2 运行时间
<强> 2. Proxies 强>
Hibernate返回的实体对象是真实类型的代理。