Hibernate中get和load的區別
Hibernate在國內沒有國外那麼火,國內幾乎被Mybatis霸佔,因爲Hibernate的底層採用了大量的反射機制與緩存機制,所以很多的地方都需要進行調優,而Mybatis的操作幾乎是傻瓜式。有時候因爲一點點的配置差異會導致項目響應出現極大的差異,今天我們就來說一下Hibernate中session的兩個獲取對象方法
Session對象有兩個獲取單個對象的方法,分別是get和load,它們的區別如下
查詢的時機不一樣
- get方法任何時刻都是立即加載,只要調用get方法,先從一級緩存裏面查找,如果沒有那麼就發起數據庫查詢。
- load方法默認情況下是延遲加載,先從一級緩存裏面找,沒有再找二級緩存,如果都沒有那麼就返回一個字節碼加強的代理對象,當真正用到對象的非OID字段數據才發起查詢。
返回的結果不一樣
- get方法永遠返回查詢的實體類對象,如果沒有查詢到值,那麼返回Null
- load方法返回的是代理對象,如果沒有查詢到值,那麼拋出異常
加載時機不同
- 立即加載:是不管用不用馬上查詢。
- 延遲加載:是等到真正用的時候才發起查詢。
下面我們通過實際的代碼測試來觀看get和load的不同
測試環境:IDEA、Hibernate 5.4.10.Final、JDK 13
1、Get方式獲取數據的DeBug測試:
2、Load方式DeBug測試相同的代碼
類的懶加載配置
若是有時候想用Load卻不想讓它懶加載,那麼可以進行以下的配置,讓其懶加載失效
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<!--映射文件:映射一個實體類對象,描述一個對象最終可以直接保存對象數據到數據庫中 -->
<!-- package:要映射的對象所在的包(可選,如果不指定,此文件下所有的類都要指定全路徑)
auto-import 默認爲true,在寫HQL的時候自動導入包名如果指定爲false,在寫HQL的時候必須要寫上類的全名-->
<hibernate-mapping package="com.mokerson.hibernate.pojo">
<!--
name:對應的是類名
table:對應數據庫中的表名
schema:數據庫的實例
lazy:是否開啓懶加載
-->
<class name="Invitation" table="invitation" schema="tribune" lazy="true">
<id name="id" column="id"/>
<property name="title" column="title"/>
<property name="summary" column="summary"/>
<property name="author" column="author"/>
<property name="createDate" column="createDate"/>
<!-- 一對多關聯映射配置(通過帖子找到回覆)
Dept映射關鍵點:
1.指定映射的集合屬性:replyDetails
2.集合屬性對應的集合表:reply_detail
3.集合表的外鍵字段:invId
4.集合元素的類型-->
<set name="replyDetails" table="reply_detail">
<key column="invId"/>
<one-to-many class="ReplyDetail"/>
</set>
</class>
</hibernate-mapping>
Hibernate使用的好不好,就在於這些小細節。
還有一些地方用到了懶加載機比如Query對象的list和iterator
請參考我的另一篇博客