【发布时间】:2011-01-12 15:07:22
【问题描述】:
什么是 Java 中的延迟加载?我不明白这个过程。谁能帮我理解延迟加载的过程?
【问题讨论】:
标签: java hibernate orm lazy-loading
什么是 Java 中的延迟加载?我不明白这个过程。谁能帮我理解延迟加载的过程?
【问题讨论】:
标签: java hibernate orm lazy-loading
假设您有一个父级,并且该父级有一组子级。 Hibernate 现在可以“延迟加载”子级,这意味着它在加载父级时实际上并没有加载所有子级。相反,它会在请求时加载它们。你可以明确地请求这个,或者,这是更常见的,当你尝试访问一个孩子时,hibernate会自动加载它们。
延迟加载有助于显着提高性能,因为您通常不需要子级,因此不会加载它们。
还要注意 n+1 问题。当您访问集合时,Hibernate 实际上不会加载所有子项。相反,它将单独加载每个孩子。当迭代集合时,这会导致对每个孩子的查询。为了避免这种情况,您可以欺骗 hibernate 同时加载所有子项,例如通过调用 parent.getChildren().size()。
【讨论】:
“延迟加载”是指仅在您实际第一次访问实体时加载实体。
pattern 是这样的:
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();
}
【讨论】:
Martin Fowler 在Patterns of Enterprise Application Architecture 中这样定义Lazy Load 模式:
一个不包含您需要的所有数据但知道如何获取数据的对象。
因此,在加载给定对象时,我们的想法是不要急切地加载您可能不会立即使用的相关对象,以节省相关的性能成本。相反,相关对象仅在使用时才会加载。
这不是特定于数据访问和 Hibernate 的模式,但它在此类领域特别有用,并且 Hibernate 支持延迟加载一对多关联和单点关联(一对一和多对一)也在某些条件下。 在 Hibernate 3.0 参考文档的Chapter 19 中更详细地讨论了惰性交互。
【讨论】:
bydefault延迟加载是true.Lazy加载意味着在执行SELECT查询时,它将不会点击数据库。它将等待 getter 函数,即当我们需要时,它将从数据库中获取。 例如: 你是一个有很多玩具的孩子的父母。但当前的问题是,无论何时你给他打电话(我们假设你有一个男孩),他都会带着他所有的玩具来找你。现在这是一个问题,因为您不希望他一直随身携带他的玩具。 因此,作为理性的父母,您可以直接将孩子的玩具定义为 LAZY。现在,无论何时你打电话给他,他都会不带玩具地来找你。
【讨论】:
用外行的话来说,这就像你在做蛋糕,你需要从冰箱里拿出 5-10 种配料。您有两种选择,从冰箱中取出所有食材并将其放在厨房平台上,或者在需要时携带您想要的物品。
类似地,在急切加载中,您会获取有关 bean 及其相关类的所有信息(不是子关系或 is-a 关系,但有关系,即蛋糕有面粉、有牛奶、有奶油等),并且在懒惰的情况下加载,首先你只带上它的标识符和来自同一张桌子的值(必要的成分,首先你需要在你的碗里,以防蛋糕)。来自其他表的所有信息都将在需要/使用时获取。
【讨论】:
延迟获取决定是否在加载父对象时加载子对象。
您需要设置父类的相应休眠映射文件。
Lazy = true(表示不加载孩子)
默认情况下,子对象的延迟加载为 true。
这确保子对象不会被加载,除非它们通过在父对象上调用 getChild() 方法在应用程序中显式调用。在这种情况下,当实际调用 getChild() 时,hibernate 会发出一个新的数据库调用来加载子对象在父对象上。
但在某些情况下,您确实需要在加载父对象时加载子对象。 只需设置lazy=false,当从数据库加载父级时,休眠将加载子级。
示例: 如果你有一张桌子? 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>
在上面的配置中。
If lazy="false" : - 当您加载 Employee 对象时,子对象 Address 也被加载并设置为 setAddresss() 方法。
如果您调用 employee.getAdress() 则加载的数据返回。没有新的数据库调用。
如果lazy="true" :- 这是默认配置。如果你没有提到那么休眠考虑lazy=true。
当您加载 Employee 对象时,未加载子对象 Adress。您需要额外调用数据库来获取地址对象。
如果您调用employee.getAdress(),那么那个时候数据库查询会触发并返回结果。新的数据库调用。
【讨论】:
延迟加载?好吧,这只是意味着不会立即获取子记录,而是会在您尝试访问它们时自动获取它们。
【讨论】:
延迟加载允许您延迟关联检索或更好地控制获取策略。
当您使用 EAGER 加载时,您定义了一个在查询时无法覆盖的全局获取计划,这意味着您受限于在设计实体模型时做出的决定。 EAGER fetching is a code smell,因为获取策略是查询时策略,它可能因业务用例而异。
fetching strategy 是一个非常重要的方面,因为过多的 EAGER 获取会导致严重的性能相关问题。
【讨论】:
懒惰设置决定是否在加载Parent Object的同时加载子对象。需要设置父类各自的hibernate映射文件。Lazy = true(表示不加载child)默认懒加载child对象为真。这确保了子对象不会被加载,除非它们通过在父对象上调用 getChild() 方法在应用程序中显式调用。在这种情况下,当 getChild() 在父对象上被实际调用时,hibernate 会发出一个新的数据库调用来加载子对象object.But 在某些情况下,您确实需要在加载父对象时加载子对象。只需设置lazy=false,当从数据库加载父级时,休眠将加载子级。示例lazy=true(默认)如果不经常需要,可以将User类的地址子级设置为惰性。lazy=false但您可能需要加载每当您为在线书店处理图书时,Book 父级的 Author 对象。
【讨论】:
延迟加载是一种设计模式 常用于计算机编程 推迟对象的初始化 直到需要它的时候。 它可以有助于提高效率 程序的运行是否正确并且 适当使用
维基百科
来自 hibernate.org 的 Lazy Loading 的链接
【讨论】:
这只是意味着加载您当前需要的数据,而不是一次加载您现在不会使用的一大堆数据。从而使应用程序加载时间比平时更快。
【讨论】:
令人惊讶的是,没有一个答案谈论它是如何通过屏幕后的休眠来实现的。
Lazy loading 是一种设计模式,出于性能原因,它在 hibernate 中有效使用,其中涉及以下技术。
1.字节码检测:
使用 hibernate hooks 增强基类定义以拦截对该实体对象的所有调用。
在编译时或运行[加载]时完成
1.1 编译时间
编译后操作
主要由 maven/ant 插件提供
1.2 运行时间
Hibernate 返回的实体对象是真实类型的代理。
【讨论】:
Hiberante 支持实体和集合的延迟初始化功能。 Hibernate 引擎仅加载我们正在查询的那些对象,而不加载其他实体或集合。
lazy="false" 默认加载初始化提到唯一的孩子是懒惰的。如果是 true 是父母正在加载不支持孩子
【讨论】:
懒惰设置决定是否在加载Parent Object的同时加载子对象。需要设置父类各自的hibernate映射文件。Lazy = true(表示不加载child)默认懒加载child对象为真。
【讨论】: