程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> 容器的延遲初始(Lazy Initialization)

容器的延遲初始(Lazy Initialization)

編輯:關於JAVA

有時候您只是想要獲得物件中某個屬性的資料,如果您的物件中包括Set等容器物件,若從資料庫中載入資料時全部載入所有的物件,卻只是為了取得某個屬性,顯然的這樣很沒有效率。

以Set中的范例來說,如果您只是想取得物件之後,顯示物件的某些屬性,例如name屬性:

Session session = sessionFactory.openSession();
User user = (User) session.load(User.class, new Integer(1));
System.out.println(user.getName());
session.close();

在這個例子中,email的資訊不必要從資料庫中全部載入,在Hibernate中支援容器的延遲初始(Lazy onitialization),只有在真正需要容器物件中的資料時,才從資料庫中取得資料,預設容器類會使用延遲加載的功能,例如上面的程式實際上會使用以下的SQL:

Hibernate: select user0_.id as id0_, user0_.name as name0_0_ from user user0_ where user0_.id=?

可以藉由映射文件中的lazy屬性來設定是否使用延遲初始,例如在映射文件中如下設定:

User.hbm.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping
   PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
   "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

   <class name="onlyfun.caterpillar.User" table="user">
     ....
     <set name="emails" table="email" lazy="false">
       <key column="id"/>
       <element type="java.lang.String"
           column="address"/>
     </set>
   </class>

</hibernate-mapping>

由於lazy屬性被設定為false,延遲初始的功能被關閉,所以上面的程式會使用以下的SQL來查詢:

Hibernate:
select user0_.id as id0_, user0_.name as name0_0_
from user user0_ where user0_.id=?
Hibernate:
select emails0_.id as id0_, emails0_.address as address0_
from email emails0_ where emails0_.id=?

所有的容器物件之資料一並被查詢了,即使程式中還不會使用到容器中的物件資訊。

在啟用延遲初始的情況下,如果如下查詢資料:

Session session = sessionFactory.openSession();
User user = (User) session.load(User.class, new Integer(1));
System.out.println(user.getName());
Iterator iterator = user.getEmails().iterator();
while(iterator.hasNext()) {
   System.out.println(iterator.next());
}
session.close();

在開啟SQL顯示的情況下,會顯示以下的內容:

Hibernate:
select user0_.id as id0_, user0_.name as name0_0_
from user user0_ where user0_.id=?

caterpillar

Hibernate:
select emails0_.id as id0_, emails0_.address as address0_
from email emails0_ where emails0_.id=?

[email protected]
[email protected]
可以看到,只有在需要查詢容器中物件時,才會向資料庫索取資料。

使用延遲初始時,由於在需要資料時會向資料庫進行查詢,所以session不能關閉,如果關閉會丟出LazyInitializationException 例外,例如下面的程式就會丟出例外:

Session session = sessionFactory.openSession();
User user = (User) session.load(User.class, new Integer(1));
System.out.println(user.getName());

session.close();

Iterator iterator = user.getEmails().iterator();
while(iterator.hasNext()) {
   System.out.println(iterator.next());
}

如果您使用了延遲初始,而在某些時候仍有需要在session關閉之後取得相關物件,則可以使用Hibernate.initialize()來先行載入相關物件,例如:

Session session = sessionFactory.openSession();
User user = (User) session.load(User.class, new Integer(1));
System.out.println(user.getName());

Hibernate.initialize(user.getEmails()); // 先載入容器中的物件

session.close();

Iterator iterator = user.getEmails().iterator();
while(iterator.hasNext()) {
   System.out.println(iterator.next());
}

即使啟用延遲初始,在Hibernate.initialize()該行,email容器中的物件已經被載入,所以即使關閉session也無所謂了,這種情況發生在某個情況下,您啟用了延遲初始,而使用者操作過程中,會在稍後一陣子才用到email容器,您不能浪費session在這段時間的等待上,所以您先行載入容器物件,直接關閉session以節省資源。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved