【问题标题】:How Session.get method works in hibernateSession.get 方法如何在休眠中工作
【发布时间】:2015-01-12 07:13:34
【问题描述】:

我试图了解对象初始化如何通过 Session Get 方法对返回的对象起作用。请验证我的理解。当它执行时,它会在一级缓存中检查具有给定标识符的对象,然后是二级缓存(如果已配置),如果未找到则触发选择查询以从数据库中检索数据。 我的问题是,它是否在选择查询中包含为延迟加载配置的关联,或者在返回的对象中为此类关联设置了空值?

如果是这种情况,那么 session.get 不会对返回的对象进行完整的初始化,这与网络上大多数 hibernate 教程中所写的内容相矛盾。

【问题讨论】:

    标签: java hibernate get


    【解决方案1】:

    Hibernate Session 提供了不同的方法来从数据库中获取数据。其中两个是 - get() 和 load()。 get() 通过从数据库或休眠缓存中获取对象来返回对象。 当我们使用 get() 来检索不存在的数据时,它会返回 null,因为它会在调用时尝试加载数据。

    • 当我们想确保数据库中存在数据时,我们应该使用 get()。

    例如:

    在 Stock 应用程序中,Stock 和 StockTransactions 应该具有“一对多”的关系,当您要保存股票交易时,通常会声明如下内容。

           Stock stock = (Stock)session.get(Stock.class, new Integer(2));
           StockTransaction stockTransactions = new StockTransaction();
           //set stockTransactions detail
           stockTransactions.setStock(stock);        
           session.save(stockTransactions);
    

    输出:

    Hibernate: 
    select ... from mkyong.stock stock0_ 
    where stock0_.STOCK_ID=?
    Hibernate: 
    insert into mkyong.stock_transaction (...) 
    values (?, ?, ?, ?, ?, ?)
    

    在 session.get() 中,Hibernate 将访问数据库以检索 Stock 对象并将其作为对 StockTransaction 的引用。

    【讨论】:

      【解决方案2】:

      回答问题:

      它是否包括为延迟加载配置的选择查询中的关联或在返回的对象中为此类关联设置了空值?

      1) session.get() 启动懒惰的东西。绝不。事实上,这是设计的中心思想。否则 - 我们将能够在一次 SHOT 中加载整个数据库(在一次对 session.get() 的 JAVA 调用中)

      2) 还有 不会 改为 null。每个引用或集合将由 proxy 表示。这是我们可以避免一次性加载compelte DB的方法(所有东西都用一种方法get初始化)。因为每个代理实际上都是一个承诺——一旦我们触摸它……它就会加载真实数据。

      等等。因此,get 是一种非常安全的方式,如何接收配置的尽可能少的数据....

      【讨论】:

        【解决方案3】:

        简单

        get()方法被调用时,会直接命中数据库,取结果返回。如果没有找到匹配的字段,它会很乐意返回 null。

        根据引用的注释,Lazy 或 Eager,将返回数据。如果Lazy,则返回proxy而不是null,如果Eager,则返回完全初始化的对象。

        最好在后端监控查询,以便更好地理解。

        【讨论】:

        • 它如何在实体中由开发人员配置的关联上配置的获取模式(延迟或早期)的上下文中工作?
        【解决方案4】:

        1) 映射 T_CUSTOMER DB 表的客户实体类:

        @Entity
        @Table(name= “T_CUSTOMER”)
        public class Customer {
            @Id
            @Column (name=“cust_id”)
            private Long id;
        
            @OneToMany(fetch=FetchType.EAGER)
            @JoinColumn (name=“cid”)
            private Set<Address> addresses;
            …
            …
            …
        }
        

        2) 映射T_ADDRESS DB表的地址实体类:

        @Entity
        @Table(name= “T_ADDRESS”)
        public class Address {
            // Fields and Properties
        }
        

        考虑这个客户表:

        ----------------------------------------------------------------------------
        | Cust_id  | Cust_firstname | Cust_lastname  |  Cust_email  |  Cust_mobile |
        ----------------------------------------------------------------------------
        |   101    |       XXXX     |    YYYYY         |xxx@xyz.com |  8282263131  |
        ----------------------------------------------------------------------------
        

        上述客户表有一条 cust_id 为 101 的记录。

        现在考虑这个地址表:

        ----------------------------------------------------------------------------
        | id       |   street    |    suburb     |   city   |  zipcode |    cid    |
        ----------------------------------------------------------------------------
        |   1      |   streetX   |    AreaY      | cityZ    |  54726   |    101    |
        ----------------------------------------------------------------------------
        |   2      |   streetXA  |    AreaYB     | cityZS   |  60660   |    101    |
        ----------------------------------------------------------------------------
        

        现在当你调用时:

        Customer cust = (Customer)session.get(Customer.class, 101);
        

        然后 Hibernate 将触发 SQL 查询,例如:

        1).EAGER LOADING 的情况下:

        SELECT * FROM T_CUSTOMER cust JOIN T_ADDRESS add ON cust.cust_id=add.cid

        即,它将加载与 T_CUSTOMERS 表及其关联表相关的所有数据,在本例中为 T_ADDRESS 表。

        2). LAZY LOADING 的情况:

        SELECT * FROM T_CUSTOMER WHERE cust_id=101;
        

        因此,它只获取与 T_CUSTOMER 表对应的数据,并使用 @Radim Köhler 上面所说的 T_ADDRESS 表的代理。只有当您调用时,它才会从 T_ADDRESS TABLE 中获取数据:

        cust.getAddresses();
        

        【讨论】:

        • 在EAGER LOADING的情况下,需要显式配置fetching strategy="JOIN",默认值为"select"
        • @Vinit89 是的,我想我在复制其他答案的内容时忘记编辑它了。感谢您指出。
        • 我认为 cust.getAddresses() 只返回代理对象。它不会触发选择查询,因为 cust 不是代理对象。请验证它。
        猜你喜欢
        • 2018-02-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-03-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-13
        相关资源
        最近更新 更多