【问题标题】:What is lazy loading in Hibernate?Hibernate 中的延迟加载是什么?
【发布时间】:2011-01-12 15:07:22
【问题描述】:

什么是 Java 中的延迟加载?我不明白这个过程。谁能帮我理解延迟加载的过程?

【问题讨论】:

    标签: java hibernate orm lazy-loading


    【解决方案1】:

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

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

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

    【讨论】:

    • 应该使用 Hibernate.initialize(parent.getChildren())
    • “当您访问集合时......它将单独加载每个孩子”的说法实际上是完全不准确的。它实际上完全相反。任何对 parent.getChildren() 的取消引用都会导致 Hibernate 在一个数据库查询中加载集合中的所有子项。除非您使用了非常特殊的“额外延迟”延迟加载提示。或者除非您将集合缓存在二级缓存中并且相关的子项也不会被缓存。
    • 哦,堆栈溢出 - 在页面底部找到最佳答案 ;-)
    【解决方案2】:

    “延迟加载”是指在您实际第一次访问实体时加载实体。

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

    【讨论】:

      【解决方案3】:

      Martin Fowler 在Patterns of Enterprise Application Architecture 中这样定义Lazy Load 模式:

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

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

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

      【讨论】:

        【解决方案4】:

        bydefault延迟加载是true.Lazy加载意味着在执行SELECT查询时,它将不会点击数据库。它将等待 getter 函数,即当我们需要时,它将从数据库中获取。 例如: 你是一个有很多玩具的孩子的父母。但当前的问题是,无论何时你给他打电话(我们假设你有一个男孩),他都会带着他所有的玩具来找你。现在这是一个问题,因为您不希望他一直随身携带他的玩具。 因此,作为理性的父母,您可以直接将孩子的玩具定义为 LAZY。现在,无论何时你打电话给他,他都会不带玩具地来找你。

        【讨论】:

          【解决方案5】:

          用外行的话来说,这就像你在做蛋糕,你需要从冰箱里拿出 5-10 种配料。您有两种选择,从冰箱中取出所有食材并将其放在厨房平台上,或者在需要时携带您想要的物品。

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

          【讨论】:

            【解决方案6】:

            延迟获取决定是否在加载父对象时加载子对象。 您需要设置父类的相应休眠映射文件。 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(),那么那个时候数据库查询会触发并返回结果。新的数据库调用。

            【讨论】:

            • Employee 和 Address 在这种情况下没有父子关系。这是'has-a'关系
            • 这是聚合而不是继承。
            【解决方案7】:

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

            【讨论】:

              【解决方案8】:

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

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

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

              【讨论】:

                【解决方案9】:

                懒惰设置决定是否在加载Parent Object的同时加载子对象。需要设置父类各自的hibernate映射文件。Lazy = true(表示不加载child)默认懒加载child对象为真。这确保了子对象不会被加载,除非它们通过在父对象上调用 getChild() 方法在应用程序中显式调用。在这种情况下,当 getChild() 在父对象上被实际调用时,hibernate 会发出一个新的数据库调用来加载子对象object.But 在某些情况下,您确实需要在加载父对象时加载子对象。只需设置lazy=false,当从数据库加载父级时,休眠将加载子级。示例lazy=true(默认)如果不经常需要,可以将User类的地址子级设置为惰性。lazy=false但您可能需要加载每当您为在线书店处理图书时,Book 父级的 Author 对象。

                【讨论】:

                  【解决方案10】:

                  延迟加载是一种设计模式 常用于计算机编程 推迟对象的初始化 直到需要它的时候。 它可以有助于提高效率 程序的运行是否正确并且 适当使用

                  维基百科

                  来自 hibernate.org 的 Lazy Loading 的链接

                  【讨论】:

                    【解决方案11】:

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

                    【讨论】:

                      【解决方案12】:

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

                      Lazy loading 是一种设计模式,出于性能原因,它在 hibernate 中有效使用,其中涉及以下技术。


                      1.字节码检测

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

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

                      1.1 编译时间

                      • 编译后操作

                      • 主要由 maven/ant 插件提供

                      1.2 运行时间

                      • 如果未完成编译时检测,则会在运行时创建 使用像 javassist 这样的库

                      2. Proxies

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

                      另请参阅: Javassist. What is the main idea and where real use?

                      【讨论】:

                        【解决方案13】:

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

                        lazy="false" 默认加载初始化提到唯一的孩子是懒惰的。如果是 true 是父母正在加载不支持孩子

                        【讨论】:

                          【解决方案14】:

                          懒惰设置决定是否在加载Parent Object的同时加载子对象。需要设置父类各自的hibernate映射文件。Lazy = true(表示不加载child)默认懒加载child对象为真。

                          【讨论】:

                            猜你喜欢
                            • 2010-09-07
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 1970-01-01
                            • 2021-02-21
                            • 1970-01-01
                            相关资源
                            最近更新 更多