hibernate的load和get方法的區別

hibernate的load和get方法的區別
2008-07-09 11:14

1)當數據庫不存在對應ID數據時,調用load()方法將會拋出ObjectNotFoundException異常,get()方法將返回null.下面是一個簡單的測試數據庫中沒有id爲2的person

2)也就是延時加載的區別。load的方法默認要加載的對象是存在數據庫中的,返回的是一個代理對象而不是一個真正的類實例,當用到具體與數據庫有關的數據時候才查詢數據庫,而get方法直接查詢數據庫,返回類的實例。例如上面的例子,運行到(1)直接輸出sql語句,而(3)卻沒有輸出,在(5)輸出了一條sql語句,由於所查詢的對象不存在拋出ObjectNotFoundException異常。關於類的代理對象可以通過debug調試的到。但是如果在內部內存中存在所要查詢的對象,無論對象是代理的(load出來的)還是類的實例(get出來的)都會返回內存中的形態。

3)第三點區別就是:“,get方法首先查詢session緩存,沒有的話查詢二級緩存,最後查詢數據庫;反而load方法創建時首先查詢session緩存,沒有就創建代理,實際使用數據時才查詢二級緩存和數據庫。”這是從別的地方聽說的。

 

================================================

2008-05-22 11:45

面試的題目是load和get方法的區別,平時也就知道用這兩個方法,還真不知道有什麼區別!回來後查了查,自己做了一下驗證終於理解了二者的不同!一下哦我們以一個例子來講解一下。

 

package hib;

/**
* @hibernate.class table="PERSON"
* @author Administrator
*
*/
public class Person {

private int id;

private String name = "jiaji";

/**
* @hibernate.id generator-class="native"
* @return the id
*/
public int getId() {
   return id;
}

/**
* @param id
*            the id to set
*/
public void setId(int id) {
   this.id = id;
}

/**
* @hibernate.property length="20"
* @return the name
*/
public String getName() {
   return name;
}

/**
* @param name
*            the name to set
*/
public void setName(String name) {
   this.name = name;
}

}

映射文件Personhbm.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="hib.Person" table="PERSON" lazy="true">

   <id name="id" column="id" type="int">
    <generator class="native">
    </generator>
   </id>

   <property name="name" type="java.lang.String" update="true"
    insert="true" column="name" length="20" />

</class>

</hibernate-mapping>

hibernate配置文件,爲了查看試驗結果設置 <property name="show_sql">true</property>由於顯示sql語句

<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
          "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
          "
http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<!-- Generated by MyEclipse Hibernate Tools.                   -->
<hibernate-configuration>

<session-factory>
<property name="connection.username">root</property>
<property name="connection.url">
   jdbc:mysql://localhost:3306/data
</property>
<property name="dialect">
   org.hibernate.dialect.MySQLDialect
</property>
<property name="myeclipse.connection.profile">mysql</property>
<property name="connection.password">jiajw</property>
<property name="connection.driver_class">
   com.mysql.jdbc.Driver
</property>

<property name="jdbc.fetch_size">50</property>
<property name="show_sql">true</property>
<property name="createtable">false</property>
<property name="updatetable">true</property>
<property name="c3p0.min_size">2</property>
<property name="c3p0.max_size">5</property>
<property name="c3p0.max_statements">100</property>
<property name="c3p0.idle_test_period">5000</property>
<mapping resource="hib/Person.hbm.xml" />

</session-factory>

</hibernate-configuration>

言歸正傳,一下介紹兩種方法的三點區別:

1)當數據庫不存在對應ID數據時,調用load()方法將會拋出ObjectNotFoundException異常,get()方法將返回null.下面是一個簡單的測試數據庫中沒有id爲2的person。

package hib;

import org.hibernate.Session;
import org.hibernate.Transaction;

public class Test {

public static void main(String[] args) {
   Session session = HibernateSessionFactory.getSession();
   Transaction transaction = session.beginTransaction();
   Person p = (Person) session.get(Person.class, 2);(1)
   System.out.println("p="+p);(2)
   Person p1 = (Person) session.load(Person.class,2);(3)
   System.out.println("arrived here");(4)
   System.out.println(p1.getName());(5)
   session.close();
}
}

 

運行結果如下

 

 

 

 

 

 

 

2)也就是延時加載的區別。load的方法默認要加載的對象是存在數據庫中的,返回的是一個代理對象而不是一個真正的類實例,當用到具體與數據庫有關的數據時候才查詢數據庫,而get方法直接查詢數據庫,返回類的實例。例如上面的例子,運行到(1)直接輸出sql語句,而(3)卻沒有輸出,在(5)輸出了一條sql語句,由於所查詢的對象不存在拋出ObjectNotFoundException異常。關於類的代理對象可以通過debug調試的到。但是如果在內部內存中存在所要查詢的對象,無論對象是代理的(load出來的)還是類的實例(get出來的)都會返回內存中的形態。

Session session = HibernateSessionFactory.getSession();
   Transaction transaction = session.beginTransaction();
   Person p = (Person) session.get(Person.class, 1);
     System.out.println("arrived here");
   System.out.println(p.getName());
   session.close();

調試結果爲:

如果把get方法改成 load方法結果就不一樣

 

 

3)第三點區別就是:“,get方法首先查詢session緩存,沒有的話查詢二級緩存,最後查詢數據庫;反而load方法創建時首先查詢session緩存,沒有就創建代理,實際使用數據時才查詢二級緩存和數據庫。”這是從別的地方聽說的。

 

 

hibernate get load 區別

1、hibernate中get方法和load方法的根本區別在於:如果你使用load方法,hibernate認爲該id對應的對象(數據庫記錄)在數據庫中是一定存在的,所以它可以放心的使用,它可以放心的使用代理來延遲加載該對象。在用到對象中的其他屬性數據時才查詢數據庫,但是萬一數據庫中不存在該記錄,那沒辦法,只能拋異常,所說的load方法拋異常是指在使用該對象的數據時,數據庫中不存在該數據時拋異常,而不是在創建這個對象時。由於session中的緩存對於hibernate來說是個相當廉價的資源,所以在load時會先查一下session緩存看看該id對應的對象是否存在,不存在則創建代理。所以如果你知道該id在數據庫中一定有對應記錄存在就可以使用load方法來實現延遲加載。
對於get方法,hibernate會確認一下該id對應的數據是否存在,首先在session緩存中查找,然後在二級緩存中查找,還沒有就查數據庫,數據庫中沒有就返回null。

2、雖然好多書中都這麼說:“get()永遠只返回實體類”,但實際上這是不正確的,get方法如果在session緩存中找到了該id對應的對象,如果剛好該對象前面是被代理過的,如被load方法使用過,或者被其他關聯對象延遲加載過,那麼返回的還是原先的代理對象,而不是實體類對象,如果該代理對象還沒有加載實體數據(就是id以外的其他屬性數據),那麼它會查詢二級緩存或者數據庫來加載數據,但是返回的還是代理對象,只不過已經加載了實體數據。

3 get方法首先查詢session緩存,沒有的話查詢二級緩存,最後查詢數據庫;反而load方法創建時首先查詢session緩存,沒有就創建代理,實際使用數據時才查詢二級緩存和數據庫。

總之對於get和load的根本區別,一句話,hibernate對於load方法認爲該數據在數據庫中一定存在,可以放心的使用代理來延遲加載,如果在使用過程中發現了問題,只能拋異常;而對於get方法,hibernate一定要獲取到真實的數據,否則返回null。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章