Hibernate之N+1问题
什么是hibernate的N+1問題?先了解這樣一個描述:
多個學生可以對應(yīng)一個老師,所以student(n)---teacher(1)。Stu類中有一個屬性teacher。在hibernate配置文件中,Stu.hbm.xml中這樣配置teacher
<many-to-one name="teacher" class="com.ssh.shop.model.Account" lazy="false" ><column name="tid"/> <!--相當于 外鍵 --> </many-to-one>上面的 lazy="false",表示級聯(lián)查詢關(guān)聯(lián)對象,但是當使用session.query()執(zhí)行查詢Student后打印sql語句:
select * from student ...select * from teacher where tid=? select * from teacher where tid=? select * from teacher where tid=?...查看sql發(fā)現(xiàn),查了一條student語句,查了N條與stu關(guān)聯(lián)的teacher語句。
配置里面,除了配置lazy之外,還有個配置是fetch,fetch有2個選項:select和join。當fetch=join時,會不會只查一條語句呢?答案是:不會。原因(后續(xù)補...)
所以,這里就出現(xiàn)了N+1的問題
N+1問題:執(zhí)行一條select語句查詢當前表,執(zhí)行N條語句查詢與當前表關(guān)聯(lián)的表,N是不同的關(guān)聯(lián)數(shù)。效率很差
lazy:是否及時加載,false是及時加載
fetch:以什么樣的方式加載,select(默認):select語句查詢;join:以join語句查詢
注意:join在many-to-one中是無效的,在one-to-many中有效。
A表===關(guān)聯(lián)===>B表===關(guān)聯(lián)===>C表...(關(guān)系多的話要一個表一個表的關(guān)聯(lián)...)
所以,在任何情況下,都不要在xml中配置lazy="false" fetch="join"
N+1解決方案:
自己寫hql語句,如加入 hql = "from Stu s left join fetch s.teacher where s.sex = :sex",
left join代表左外連接,fetch代表把查出來的s.teacher抓取到Category對象中。
如果不寫fetch,則executeQuery這條hql語句,會得到一個對象數(shù)組 [Student[id,name,sex...] ,Teacher[id,name,...] ] ?(可以自己debug查看執(zhí)行結(jié)果)
對應(yīng)的sql語句如下:
?
如果不寫hql,而又配置了many-to-one,則默認為懶加載關(guān)聯(lián),lazy="true",拋異常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
因為session在加載Stu后關(guān)閉,再去加載對應(yīng)的關(guān)聯(lián)teacher的時候,session已經(jīng)關(guān)閉了。
轉(zhuǎn)載于:https://www.cnblogs.com/yangzhenlong/p/5077392.html
總結(jié)
以上是生活随笔為你收集整理的Hibernate之N+1问题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: POJ-1414 Life Line
- 下一篇: HDU2015校赛 The Countr