面試的題目是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。