簡體   English   中英

Session.get方法如何在hibernate中工作

[英]How Session.get method works in hibernate

我試圖通過Session Get方法了解對象初始化如何為返回的對象工作。請驗證我的理解。 執行時,它會檢查第一級緩存中具有給定標識符的對象,然后檢查第二級緩存(如果已配置),如果未找到,則觸發select查詢以從數據庫中檢索數據。 我的問題是,它是否包含為延遲加載配置的select查詢中的關聯,或者為返回對象中的此類關聯設置空值?

如果是這種情況,那么session.get不會對返回的對象進行完整的初始化,這與Web上可用的大多數hibernate教程所寫的內容相矛盾。

Hibernate Session提供了從數據庫中獲取數據的不同方法。 其中兩個是 - get()和load()。 get()通過從數據庫或從hibernate緩存中獲取對象來返回對象。 當我們使用get()來檢索不存在的數據時,它返回null,因為它會在調用時盡快加載數據。

  • 當我們想確保數據庫中存在數據時,我們應該使用get()。

例如 :

在股票應用程序中,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的引用。

回答這個問題:

是否包含為延遲加載配置的select查詢中的關聯,或者為返回對象中的此類關聯設置空值?

1) session.get() 不會啟動懶惰的東西。 決不。 實際上,這是設計的核心思想。 否則 - 我們將能夠在一個SHOT中加載整個DB(在一個JAVA調用session.get()

2)而且也不會為空。 每個參考或集合將由代理表示。 這就是我們如何避免一次性加載強制數據庫的方式(所有用一個方法get初始化的東西)。 因為每個代理實際上都是一個承諾 - 一旦我們觸摸它......它將加載真實數據。

等等。 因此獲得非常安全的方式如何收集盡可能少的數據....

只是

當調用get()方法時,它將直接命中數據庫,獲取結果並返回。 如果找不到匹配的字段,它將很樂意返回null。

根據引用的注釋, Lazy或Eager ,將返回數據。 如果是Lazy ,則返回代理而不是null,如果Eager ,將返回完全初始化的對象。

最好監控后端的查詢,以便更好地理解。

1)映射T_CUSTOMER數據庫表的客戶實體類:

@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
}

請考慮此Customers表:

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

Above customers表有一條記錄,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)。 我的懶惰加載案例

SELECT * FROM T_CUSTOMER WHERE cust_id=101;

因此,它只獲取對應於T_CUSTOMER表的數據,並使用Proxy作為T_ADDRESS表,如上所述@RadimKöhler。 它只會在您調用時從T_ADDRESS TABLE獲取數據:

cust.getAddresses();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM