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