1. 程式人生 > >Hibernate深入之get()與load()懶載入

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

getload

一個是直接載入,並不是直接去資料庫查詢,如果快取裡有,首先到快取裡找,快取分為一級快取和二級快取,首先到一級快取中查詢;

如果在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並不從資料庫載入真正的資料,而只是為該物件建立一個代理物件來代表這個物件,這個物件上的所有屬性都為預設值;只有在真正需要使用該物件的資料時才建立這個真正的物件,真正從資料庫中載入它的資料。

如果只是訪問物件標示符屬性,就沒有必要初始化程式碼。

Account acc=(Account)session.load(Account.class,new Long(1)); //返回一個代理物件

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沒有關閉時,訪問這些懶載入物件(代理物件)的屬性(getIdgetClass除外)hibernate會初始化這些代理,或用Hibernate.initialize(proxy)來初始化代理物件;當相關聯的session關閉後,再訪問懶載入的物件將出現異常。

2、 關閉延遲載入

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

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

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

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