天天看點

Hibernate深入之get()與load()懶加載

 前面講過get和load,

一個是直接加載,并不是直接去資料庫查詢,如果緩存裡有,首先到緩存裡找,緩存分為一級緩存和二級緩存,首先到一級緩存中查找;

如果在session關閉之後進行擷取類的名字之類的屬性,依然會擷取到,例:

Order od = (Order) session.get(Order.class, 1);

通過get擷取的Order類是一個持久化類,如果session關閉之後進行擷取,od.getName,它就會變成托管狀态,但是這個對象還是有的,是以沒事;

另一個是懶加載,他不會直接進行操作,就是除了擷取id(辨別符)和類.class時,擷取其他的類屬性都會進行操作,

例:

Account acc=(Account)session.load(Account.class,new Long(1)); //傳回一個代理對象

System.out.println(acc.getId);

System.out.prontln(acc.getLonginName());

這裡的1是一個代理對象,如果隻擷取他的id,則不會加載,不會出現select語句,隻有擷取除他和本身之外才會進行查找;否則通路的隻是他的代理對象而已;如果需要取消懶加載,就隻需要在你想擷取的類屬性的映射檔案的<class name=”” table=”” lazy=”false”>把他改為false就可以了,這樣懶加載就取消了,這裡隻對load管用,對get()毫無影響;

如果把他System.out.prontln(acc.getLonginName());放在session關閉之後,則會出現錯誤,因為這裡隻産生了一個代理對象,沒有真正去查,把session關之後,他會去查資料庫,要發出sql語句,因為發出sql語句需要在session裡面,是以session關了之後,就不能使用了;

接下來說一說他們之間的差別,

延遲加載的過程:通過代理(Proxy)機制來實作延遲加載。Hibernate從資料庫擷取某一個對象資料時、擷取某一個對象的集合屬性值時,或擷取某一個對象所關聯的另一個對象時,由于沒有使用該對象的資料(除辨別符外),Hibernate并不從資料庫加載真正的資料,而隻是為該對象建立一個代理對象來代表這個對象,這個對象上的所有屬性都為預設值;隻有在真正需要使用該對象的資料時才建立這個真正的對象,真正從資料庫中加載它的資料。

如果隻是通路對象标示符屬性,就沒有必要初始化代碼。

Order order=new Order();

order.setCreateTime(new Date());

order.setAccount(acc);

Session.save(order);

在這隻需要Account執行個體來建立一個新的Order訂單對象,當調用session.save(order)時,也隻需要Account的主标示符值作為外鍵儲存到訂單表的對應字段中。這樣就少執行一條select語句,進而提高查詢效率。

Hibernate中預設采用延遲加載的情況主要有以下幾種:

當調用Session上的load()方法加載一個實體時,會采用延遲加載。

當Session加載某個實體時,會對這個實體中的集合屬性值采用延遲加載。(one-to-many)

例:當Client這個類裡具有集合屬性,

Client client = (Client) session.get(Client.class, 4);

System.out.println(client.getName());

擷取他的名字,你會發現隻有一條sql語句,因為采用了延遲加載,是以如果想

取消,就在該映射檔案下<set>裡面把lazy改成false;

當Session加載某個實體時,會對這個實體所單端關聯(one-to-one, many-to-one)的另一個實體對象采用延遲加載。

能夠懶加載的對象都是被改寫過的代理對象,當相關聯的session沒有關閉時,通路這些懶加載對象(代理對象)的屬性(getId和getClass除外)hibernate會初始化這些代理,或用Hibernate.initialize(proxy)來初始化代理對象;當相關聯的session關閉後,再通路懶加載的對象将出現異常。

2、 關閉延遲加載

在加載單個實體時,如果不需要延遲加載,就可以使用session的get()方法。

當Session加載某個實體時,不需要對這個實體中的集合屬性值延遲加載,而是要立即加載。這時可以在映射檔案中針對 這個集合屬性的配置元素(<set>,<bag>,<list>…)添加屬性lazy=“false”。

當Session加載某個實體時,不需要對這個實體所單端關聯的另一個實體對象延遲加載,就可以在映射檔案中對這個單端關聯的配置元素(<one-to-one>,<many-to-one> )添加屬性lazy=“false”。

注意:one-to-one不能有constrained=true