什么是hibernate加载?
Java中的延迟加载是什么? 我不明白这个过程。 任何人都可以帮助我理解延迟加载的过程吗?
假设你有一个父母,那个父母有一个孩子的集合。 Hibernate现在可以“延迟加载”子节点,这意味着在加载父节点时实际上并没有加载所有的子节点。 相反,它会在请求时加载它们。 你可以明确地请求这个,或者这个更常见,当你尝试访问一个subprocess时,hibernate会自动加载它们。
延迟加载可以显着提高性能,因为通常你不需要孩子,所以他们不会被加载。
也要小心n + 1的问题。 当你访问集合时,Hibernate实际上不会加载所有的孩子。 相反,它会单独加载每个孩子。 当迭代集合时,这将导致每个孩子的查询。 为了避免这种情况,你可以通过调用parent.getChildren()。size()来让hibernate同时加载所有的孩子。
“延迟加载”意味着一个实体将只在您第一次实际访问该实体时加载。
模式是这样的:
public Entity getEntity() { if (entity == null) { entity = loadEntity(); } return entity; }
这样可以节省预先加载/预先填充大数据集中的所有实体的成本,而实际上您并不需要全部实体。
在Hibernate中,可以configuration为延迟加载一组子实体。 然后在PersistentSet
的方法内完成实际的延迟加载,Hibernate使用“under hoods”将实体集合指定为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在“企业应用程序体系结构模式”中定义了Lazy Load模式,如下所示:
一个对象,不包含所有你需要的数据,但知道如何得到它。
所以,加载一个给定的对象时,这个想法是不要急于加载你可能不会立即使用的相关对象来节省相关的性能成本。 相反,只有在使用时才会加载相关的对象。
这不是一个特定于数据访问和Hibernate的模式,但是在这些领域尤其有用,Hibernate支持一对多关联和单点关联的延迟加载(一对一和多对一)在一定的条件下。 在Hibernate 3.0参考文档的第19章中详细讨论了懒惰的交互。
默认情况下,延迟加载是true.Lazy加载意味着当执行select查询时不会碰到数据库。 它将等待getter函数,即当我们需要的时候,它将从数据库中获取。 例如:你是一个有很多玩具的孩子的父母。 但目前的问题是每当你打电话给他(我们假设你有一个男孩),他也带着他所有的玩具来找你。 现在这是一个问题,因为你不希望他随身携带玩具。 所以,作为父母的理由,你就直接将孩子的玩具定义为懒惰。 现在,只要你打电话给他,他就没有他的玩具来找你。
延迟提取决定是否在加载父对象时加载子对象。 你需要这样做,设置父类的各自的hibernate映射文件。 Lazy = true
(意味着不加载孩子)默认情况下,子对象的延迟加载是真实的。
这确保子对象不被加载,除非通过在父对象上调用getChild()
方法在应用程序中显式调用子对象。在这种情况下,当父对象实际上调用了getChild()
,hibernate发出新的数据库调用来加载子对象目的。
但是在某些情况下,当加载父对象时,您确实需要加载子对象。 只要让lazy = false,当从数据库加载父进程时,hibernate将加载subprocess。
例如:如果你有一个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>
在上面的configuration中。 如果lazy="false"
: – 当你加载Employee对象那个时候子对象Address也被加载并设置为setAddresss()方法。 如果你调用employee.getAdress()然后加载数据返回。没有新的数据库调用。
如果lazy="true"
: – 这是默认configuration。 如果你不提及,那么hibernate考虑lazy = true。 当你加载Employee对象的时候子对象Adress没有加载。 您需要额外的数据库调用来获取地址对象。 如果您调用employee.getAdress()
那么数据库查询触发并返回结果。 新的数据库调用。
懒加载? 那么,这只是意味着孩子logging不会立即获取,而是一旦您尝试访问孩子logging就会自动获取。
用外行人的话来说,就像你在做蛋糕,你需要从冰箱里取出5-10种食材。 你有两种select,从冰箱里拿出所有的食材,把它放在你的厨房平台上,或者当你需要的时候拿出你想要的东西。同样,在急切的加载中,你可以获取关于bean及其相关类的所有信息(不是孩子或者是一个关系,有一个关系,即蛋糕有面粉,有牛奶,有奶油等),并在懒惰加载的情况下,首先你只带来它的标识符和值来自同一个表(必要的成分,首先你需要在你的碗,以防蛋糕)..所有来自其他表格的信息都会在需要时使用。
希望这可以帮助 :)
延迟加载是计算机编程中常用的一种devise模式,用于推迟对象的初始化,直到需要的时候。 如果适当和适当地使用,它可以有助于程序运行的效率
维基百科
从hibernate.org 延迟加载链接
延迟设置决定了在加载父对象的时候是否加载子对象。你需要这样设置父类的各自的Hibernate映射文件.Lazy = true(意味着不加载子对象)默认情况下,子对象的延迟加载是真的。 这确保子对象不被加载,除非通过在父对象上调用getChild()方法在应用程序中显式调用子对象。在这种情况下,当父对象实际上调用了getChild()时,hibernate发出新的数据库调用来加载子对象object.But在某些情况下,您确实需要加载父对象时加载子对象。 只需使lazy = false,当从数据库加载父对象时,hibernate将加载子对象.Exampleslazy = true(默认)如果不需要频繁使用User类,则可以使用User类的地址子对象。lazy = false可能需要加载作者对于Book parent,每当你处理在线书店的书。
延迟初始化是性能优化。 当数据由于某种原因被认为是“昂贵的”时使用它。 例如:如果对象的hashCode值实际上可能不是调用者需要的,那么总是为对象的所有实例计算hashCode可能被认为是不必要的。 由于访问文件系统或networking比较慢,所以这些操作应该被推迟,直到它们被绝对需要。
懒惰的初始化有两个目的:延迟昂贵的操作,直到绝对必要的存储昂贵的操作的结果,这样你就不需要再次重复
Hiberante支持实体和集合的延迟初始化function。 Hibernate引擎只加载我们正在查询的对象,而不是其他实体或集合。
lazy =“false”默认情况下,加载初始化提到的唯一的孩子是lazy.in的情况下,是父母正在加载不支持孩子
延迟设置决定了在加载父对象的时候是否加载子对象。你需要设置父类的各自的Hibernate映射文件.Lazy = true(表示不加载子对象)默认情况下,子对象的延迟加载是真实的。
延迟加载允许您推迟关联检索或更好地控制提取策略。
当您使用EAGER加载时,您定义了一个全局的提取计划,在查询时不能被覆盖,这意味着您仅限于您在devise实体模型时所做的决定。 EAGER抓取是一种代码异味 ,因为抓取策略是查询时间策略,并且可能会因业务用例而不同。
抓取策略是一个非常重要的方面,因为过多的EAGER抓取会导致严重的性能相关问题。
那么它只是意味着加载你当前需要的数据,而不是一次加载一堆你现在不用的数据。 从而使应用程序加载时间比平常更快。
令人惊讶的是,没有一个答案谈论如何通过在屏幕后面hibernate来实现。
延迟加载是一种devise模式,由于性能方面的原因,在hibernate中有效地使用了这种devise模式,这涉及以下技术
1.字节代码检测 :
用hibernate 钩子增强基类的定义来拦截所有对该实体对象的调用。
在编译时完成,或运行[加载]时间
1.1 编译时间
-
编译后的操作
-
主要由maven / ant插件
1.2 运行时间
- 如果没有编译时间检测完成,这是在运行时创build的使用类似javassist的库
2.代理
Hibernate返回的实体对象是实际types的代理。
另见: Javassist。 什么是主要思想和真正的用途?