2013年7月4日 星期四

Hibernate get() vs load()

在Hibernate中載入數據常使用這兩個方法,

在看了一些書之後,

對其中的差異有了比較明確的瞭解,

查詢順序

get():

Hibernate會先確認id是否存在,然後在session緩存中尋找,

沒有的話找二級緩存,也沒有就查詢資料庫,

還是沒有就返回null。



load():

如果是默認狀態,即lazy="true",就從session緩存找,

沒有的話會先返回該物件的代理對象,

等有需要調用物件的屬性時才去找二級緩存和資料庫,

都沒有則拋出ObjectNotFoundException,

如果是lazy="false",那就是直接加載,

尋找順序同get(),但找不到也會拋出ObjectNotFoundException。

兩者差異

在都找不到資料的情況下,get()會返回NULL,load()則會拋出ObjectNotFoundException,

基本上Hibernate認為load()表示資料庫一定有資料,所以會先返回代理對象,

而get()則是直接馬上載入,到資料庫也找不到就是NULL,

這裡要注意的是,get()如果在session緩存或二級緩存中有找到代理對象,

也是會返回該代理對象,而不是一定要找到資料庫中的對象才停止,

換句話說,get()不一定會返回實體類,

但返回的代理對象裡面一定有數據,

否則也是會繼續往下找,

也由於get()一定要找到有數據的對象或者是返回NULL,

所以get()也不支援延遲加載的。

Code實作

  TestC test = (TestC) session.get(TestC.class, id);
  TestC test1 = (TestC) session.load(TestC.class, id);

第一行test會馬上去查詢,直到資料庫也找不到返回NULL。

第二行不會去資料庫查詢,不會下任何的SQL,

會返回一個TestC的代理對象。

  TestC test1 = (TestC) session.load(TestC.class, id);
  System.out.println("load id = " + test1.getId());

請注意上面這兩行,也不會下任何SQL,

第一行會在session緩存中存放一個MAP對象,

key就是id,當第二行去找TestC的id時,

裡面已經有了,所以不會去二級緩存或資料庫找。

沒有留言:

張貼留言