簡言之就是在需要的情況下才會發出 SQL 語句,將所需的資料取出。
在說到延遲加載時,會加減牽涉到快取的問題,以下再一一說明
首先以集合的 set 為例,其 lazy 屬性預設為 true,以提高較好的效能
如下所示 :
<set name="assets" order-by="id desc" lazy="false">
<key column="assettype_id" />
<one-to-many class="org.pojo.Asset" />
</set>
以下先以一個簡短的程式來介紹 Session 的 get() 和 load() 方法
首先以一個多對一的範例為主 Assettype 為一,Asset 為多 底下先看看他們的映射文件
Asset.hbm.xml
<hibernate-mapping>
<class name="org.pojo.Asset" table="t_asset" >
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<property name="price" />
<property name="verifystatus" />
<property name="remark" />
<many-to-one name="type" column="assettype_id" not-null="true"/>
</class>
</hibernate-mapping>
Assettype.hbm.xml
<hibernate-mapping>
<class name="org.pojo.Assettype" table="t_assettype">
<id name="id">
<generator class="native" />
</id>
<property name="name" />
<set name="assets" order-by="id desc" lazy="true">
<key column="assettype_id" />
<one-to-many class="org.pojo.Asset" />
</set>
</class>
</hibernate-mapping>
最後以 JUnit 來測試一下
public void testsetlazy() { SessionFactory factory = HibernateUtil.getSessionFactory(); Session session = factory.openSession(); //以 load 加載 id 為 1 的 Assettype Assettype type = (Assettype)session.load(Assettype.class, 1); //line 1 int id = type.getId(); //line 2 String name = type.getName(); //line 3 Set assets = type.getAsset(); //line 4 for(Iterator iterator = assets.iterator();iterator.hasNext();) //line 5 { Asset asset = (Asset)iterator.next(); System.out.println(asset.getName()); } }
以上面的簡短程式來示範 load() 的加載過程,
注意 Assettype.hbm.xml 的 set 集合的 lazy 屬性是設為 true(預設)
接著在以上程式中的
line 1, Hibernate 執行 load() 撈出實體時,是不會發出SQL查詢語句的
也就是說 Hibernate 並不會到資料庫裡撈出該筆對應的資料
line 2 呢? 答案也是不會的,Hibernate 同樣也是不會去資料庫裡撈出資料
因為在 line 2 執行的 getId(), 其實你在 line 1 已經告訴 Hibernate 這個 Assettype 的 id 屬性了
所以 Hibernate 當然就不會再去查詢資料了
line 3 的話,就會發出 SQL 查詢語句 以查詢出 Assettype 的 name 屬性
line 4 勒? 這是重點了,答案是不會發出 SQL 查詢語句,為什麼呢
首先因為在 Assttype.hbm.xml 的 set 的 lazy 屬性設定為懶加載,所以當你的程式
要用到該集合的時候才會執行 SQL 語句去查詢對應的 Asset ,但是注意一點的是
Set assets = type.getAsset(); 這行並不代表你有要使用它(Asset),
而真正使用的時候則是再下一行,所以
line 5 的話就會產生一條 SQL 查詢語句去查詢目前 Assettype 所對應到的所有 Asset
-------------------------------------------------------------------------------------
到這邊應該能夠了解 load() 了吧,那如果把 line 1 改成用 get() 來撈出實體呢?
那麼 line 1 應該會發出一條的SQL查詢語句了
也就是說 Hibernate 會去資料庫撈出對應資料(Assettype)
而 line 2 和 line 3 都不會再發出任何查詢語句
因為在 line 1 時,Hibernate 已經將 Assettype 實體撈出了
而接下來再 line 4 和 line 5 的解釋,則跟上面的 load() 範例一樣
--------------------------------------------------------------------------------------
到這邊以上的測試都是以 lazy 屬性為 true 而言,那如果把 lazy 設定為 false 呢
這裡以 load() 為例,
當然 line 1 還是不會發出執行 SQL 的但是到了下一行
line 2 時,他會發出兩條 SQL 的查詢語句 !! 為什麼?
注意,我們是在 set 集合上設定他不要延遲加載,也就是告訴了 Hibernate
如果要加載 Assettype 這個實體時,遇到 set 的 assets 屬性時
也請將集合所對應到的資料一並撈出,所以 Hibernate 除了發出查詢 Assettype 的
SQL查詢語句之外,還會再發出一條查詢集合所對應到的 Asset 語句
而這個情況正就是因為你在 set 集合的 lazy 屬性設定為 false 的效果
所以接下去的程式皆不會再發出任何 SQL 語句了
最後如果在 line 1 以 get() 為例來示範 lazy = "false" 時
那麼很清楚的知道 在 line 1 執行完後就會發出兩條 SQL 語句了
所以以上除了可以了解 lazy 的意涵
也能知道 get 和 load 的差別最主要就是
在 get 的時候就會直接從資料庫中將該實體撈出
而 load 則不會
沒有留言:
張貼留言