標籤:class c a strong com 使用
Hibernate N+1 問題及解決辦法
問題出現的原因:
Hibernate 中常會用到 set , bag 等集合表示 1 對多的關係,在擷取實體的時候就能根據關係將關聯的對象或者對象集取出,還可以設定 cacade 進行關聯更新和刪除。這不得不說 hibernate 的 orm 做得很好,很貼近 oo 的使用習慣了。
但是對資料庫訪問還是必須考慮效能問題的,在設定了 1 對多這種關係之後, 查詢就會出現傳說中的 n+1 問題。
一對多: 在一方,尋找得到了 n 個對象,那麼又需要將 n 個對象關聯的集合取出,於是本來的一條 sql 查詢變成了 n+1 條;
多對一: 在多方,查詢得到了 m 個對象,那麼也會將 m 個對象對應的 1 方的對象取出, 也變成了 m+1 ;
解決問題的方法:
1、 使用 fetch 抓取, Hibernate 抓取策略分為單端代理和集合代理的抓取策略。
Hibernate 抓取策略 ( 單端代理的抓取策略 ) :
保持預設也就是如下 :
<many-to-one name="clazz" cascade="save-update" fetch="select" />
fetch="select" 就是另外發送一條 select 語句抓取當前對象關聯實體或者集合設定 fetch="join"
<many-to-one name="clazz" cascade="save-update" fetch="join"/>
Hibernate 會通過 select 語句使用外串連來載入器關聯實體活集合此時 lazy 會失效
Hibernate 抓取策略 ( 集合代理的抓取策略 ) :
保持預設( fetch="select" )也就是如下 :
<set name="students" inverse="true">
<key column="clazz"/>
<one-to-many class="com.june.hibernate.Student"/>
</set>
1)fetch="select" 會另外發出一條語句查詢集合
2) 設定 fetch="join" 採用外串連集合的 lazy 失效
3) 這隻 fetch="subselect" 另外發出一條 select 語句抓取前面查詢到的所有的實體物件的關聯集合 fetch只對 HQL 查詢產生影響其他的則不會
2、 使用 map 直接搜尋需要的列
如:產品 product 和產品分類 product_category 兩張表,多對一關聯性。查詢產品列表時
select new Map(p.id as id, p.name as name, p.category.name as categoryName) from Product p