繁体   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