Hibernate深入之get()与load()懒加载
??? 前面講過get和load,一個(gè)是直接加載,并不是直接去數(shù)據(jù)庫(kù)查詢,如果緩存里有,首先到緩存里找,緩存分為一級(jí)緩存和二級(jí)緩存,首先到一級(jí)緩存中查找;
??? 如果在session關(guān)閉之后進(jìn)行獲取類的名字之類的屬性,依然會(huì)獲取到,例:
??? Order od = (Order) session.get(Order.class, 1);
??? 通過get獲取的Order類是一個(gè)持久化類,如果session關(guān)閉之后進(jìn)行獲取,od.getName,它就會(huì)變成托管狀態(tài),但是這個(gè)對(duì)象還是有的,所以沒事;
??? 另一個(gè)是懶加載,他不會(huì)直接進(jìn)行操作,就是除了獲取id(標(biāo)識(shí)符)和類.class時(shí),獲取其他的類屬性都會(huì)進(jìn)行操作,
??? 例:
??? Account? acc=(Account)session.load(Account.class,new Long(1));??? //返回一個(gè)代理對(duì)象
??? System.out.println(acc.getId);
??? System.out.prontln(acc.getLonginName());
??? 這里的1是一個(gè)代理對(duì)象,如果只獲取他的id,則不會(huì)加載,不會(huì)出現(xiàn)select語句,只有獲取除他和本身之外才會(huì)進(jìn)行查找;否則訪問的只是他的代理對(duì)象而已;如果需要取消懶加載,就只需要在你想獲取的類屬性的映射文件的<class name=”” table=”” lazy=”false”>把他改為false就可以了,這樣懶加載就取消了,這里只對(duì)load管用,對(duì)get()毫無影響;
??? 如果把他System.out.prontln(acc.getLonginName());放在session關(guān)閉之后,則會(huì)出現(xiàn)錯(cuò)誤,因?yàn)檫@里只產(chǎn)生了一個(gè)代理對(duì)象,沒有真正去查,把session關(guān)之后,他會(huì)去查數(shù)據(jù)庫(kù),要發(fā)出sql語句,因?yàn)榘l(fā)出sql語句需要在session里面,所以session關(guān)了之后,就不能使用了;
??? 接下來說一說他們之間的區(qū)別:
??? 延遲加載的過程:通過代理(Proxy)機(jī)制來實(shí)現(xiàn)延遲加載。Hibernate從數(shù)據(jù)庫(kù)獲取某一個(gè)對(duì)象數(shù)據(jù)時(shí)、獲取某一個(gè)對(duì)象的集合屬性值時(shí),或獲取某一個(gè)對(duì)象所關(guān)聯(lián)的另一個(gè)對(duì)象時(shí),由于沒有使用該對(duì)象的數(shù)據(jù)(除標(biāo)識(shí)符外),Hibernate并不從數(shù)據(jù)庫(kù)加載真正的數(shù)據(jù),而只是為該對(duì)象創(chuàng)建一個(gè)代理對(duì)象來代表這個(gè)對(duì)象,這個(gè)對(duì)象上的所有屬性都為默認(rèn)值;只有在真正需要使用該對(duì)象的數(shù)據(jù)時(shí)才創(chuàng)建這個(gè)真正的對(duì)象,真正從數(shù)據(jù)庫(kù)中加載它的數(shù)據(jù)。
??? 如果只是訪問對(duì)象標(biāo)示符屬性,就沒有必要初始化代碼。
??? Account? acc=(Account)session.load(Account.class,new Long(1));??? //返回一個(gè)代理對(duì)象
??? Order order=new Order();
??? order.setCreateTime(new Date());
??? order.setAccount(acc);
??? Session.save(order);
??? 在這只需要Account實(shí)例來創(chuàng)建一個(gè)新的Order訂單對(duì)象,當(dāng)調(diào)用session.save(order)時(shí),也只需要Account的主標(biāo)示符值作為外鍵保存到訂單表的對(duì)應(yīng)字段中。這樣就少執(zhí)行一條select語句,從而提高查詢效率。
??? Hibernate中默認(rèn)采用延遲加載的情況主要有以下幾種:
??? 當(dāng)調(diào)用Session上的load()方法加載一個(gè)實(shí)體時(shí),會(huì)采用延遲加載。
??? 當(dāng)Session加載某個(gè)實(shí)體時(shí),會(huì)對(duì)這個(gè)實(shí)體中的集合屬性值采用延遲加載。(one-to-many)
??? 例:當(dāng)Client這個(gè)類里具有集合屬性,
??????? Client client = (Client) session.get(Client.class, 4);
??????? System.out.println(client.getName());
??????? 獲取他的名字,你會(huì)發(fā)現(xiàn)只有一條sql語句,因?yàn)椴捎昧搜舆t加載,所以如果想 ?
??????? 取消,就在該映射文件下<set>里面把lazy改成false;
??? 當(dāng)Session加載某個(gè)實(shí)體時(shí),會(huì)對(duì)這個(gè)實(shí)體所單端關(guān)聯(lián)(one-to-one,? many-to-one)的另一個(gè)實(shí)體對(duì)象采用延遲加載。
??? 能夠懶加載的對(duì)象都是被改寫過的代理對(duì)象,當(dāng)相關(guān)聯(lián)的session沒有關(guān)閉時(shí),訪問這些懶加載對(duì)象(代理對(duì)象)的屬性(getId和getClass除外)hibernate會(huì)初始化這些代理,或用Hibernate.initialize(proxy)來初始化代理對(duì)象;當(dāng)相關(guān)聯(lián)的session關(guān)閉后,再訪問懶加載的對(duì)象將出現(xiàn)異常。
2、 關(guān)閉延遲加載
??? 在加載單個(gè)實(shí)體時(shí),如果不需要延遲加載,就可以使用session的get()方法。
??? 當(dāng)Session加載某個(gè)實(shí)體時(shí),不需要對(duì)這個(gè)實(shí)體中的集合屬性值延遲加載,而是要立即加載。這時(shí)可以在映射文件中針對(duì) 這個(gè)集合屬性的配置元素(<set>,<bag>,<list>…)添加屬性lazy=“false”。
??? 當(dāng)Session加載某個(gè)實(shí)體時(shí),不需要對(duì)這個(gè)實(shí)體所單端關(guān)聯(lián)的另一個(gè)實(shí)體對(duì)象延遲加載,就可以在映射文件中對(duì)這個(gè)單端關(guān)聯(lián)的配置元素(<one-to-one>,<many-to-one> )添加屬性lazy=“false”。
??? 注意:one-to-one不能有constrained=true
轉(zhuǎn)載于:https://www.cnblogs.com/pengw/p/3983167.html
總結(jié)
以上是生活随笔為你收集整理的Hibernate深入之get()与load()懒加载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Swift数据类型简介(二)
- 下一篇: WindowsPhone8可缩放图片控件