Java Session.get方法在hibernate中的工作原理

Java Session.get方法在hibernate中的工作原理,java,hibernate,get,Java,Hibernate,Get,我试图通过会话Get方法了解返回对象的对象初始化工作原理。请验证我的理解。当它执行时,它在第一级缓存中检查具有给定标识符的对象,然后在第二级缓存中检查(如果已配置),如果未找到,则触发select查询以从数据库检索数据。 我的问题是,它是否在select查询中包含为延迟加载配置的关联,或者在返回的对象中为此类关联设置了null值 如果是这种情况,则session.get不会对返回的对象进行完全初始化,这与web上大多数hibernate教程中所写的内容相矛盾。 调用get()方法时,它将直接命中

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

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

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

根据引用上的注释,惰性或急切,将返回数据。如果
Lazy
,将返回代理而不是null;如果
Eager
,将返回完全初始化的对象


为了更好地理解,最好在后端监视查询。

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

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

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

       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 query中包含配置为延迟加载的关联,或者在返回的对象中为此类关联设置了null值

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

2) 而且,也不会为空。每个引用或集合将由代理表示。这就是我们如何避免一次加载compelte DB的方法(所有东西都是用一个方法初始化的)。因为每一个代理事实上都是一个承诺——一旦我们触及它。。。它将加载真实数据

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

1)映射T_Customer DB表的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;
    …
    …
    …
}
@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  |
----------------------------------------------------------------------------
上面的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)。如果急加载:

SELECT * FROM T_CUSTOMER WHERE cust_id=101;
选择*FROM T_CUSTOMER cust JOIN T_add ON cust.cust_id=add.cid

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

2.I延迟加载的情况:

SELECT * FROM T_CUSTOMER WHERE cust_id=101;
因此,它只获取对应于T_CUSTOMER表的数据,并使用@Radim Köhler上面所说的T_ADDRESS表的代理。仅当您调用以下命令时,它才会从T_地址表中获取数据:

cust.getAddresses();

它如何在实体内开发人员配置的关联上配置的获取模式(延迟或早期)的上下文中工作?如果是紧急加载,则需要显式配置获取策略=“JOIN”,默认值为“select”@Vinit89 yes,我想我在复制另一个答案的内容时忘了编辑这个。感谢您指出这一点。我认为cust.getAddresses()只返回代理对象。它不会触发选择查询,因为cust不是代理对象。请验证它。