2015-10-15 53 views
0

我有兩個實體組和人,我使用雙向映射,在這種情況下,我有n + 1個查詢而不是一個。改善JPA性能雙向映射「n + 1選擇」

public class Person extends BaseBean { 
Group group ; 
//getter and setter 
} 
public class Groupextends BaseBean { 
List<Person> childPersons; 
//getter and setter 
} 

我使用eclipselink進行映射。

<entity name="person" class="tn.waycon.alquasar2.gp.model.Person"> 
     <attributes> 
      <many-to-one name="group" fetch="EAGER"> 
       <join-column name="group_id" /> 
      </many-to-one> 
     </attributes> 
    </entity> 

<entity name="group_of_persons" class="tn.waycon.alquasar2.gp.model.Group"> 
     <attributes>  
      <one-to-many name="childPersons" mapped-by="group" fetch="EAGER"> 
       <join-fetch>OUTER</join-fetch> 
       <cascade> 
        <cascade-all /> 
       </cascade> 
      </one-to-many> 
     </attributes> 

    </entity> 

而我使用彈簧數據jpa來獲取數據。

@Query("select p from person p left join fetch p.group") 
List<Person> getAll(); 

的問題是,當我選擇的人的名單中GETALL功能產生1個查詢,選擇所有個人和n查詢來獲取所有的人物和GROUP_ID。 這是通過GETALL()函數生成的日誌:

SELECT t1.ID,t1.activity,t1.last_name,t1.matricule,t0.NAME,t0.parent_id FROM T1 PERSON LEFT OUTER JOIN GROUP_OF_PERSONS T0 ON( t0.ID = t1.group_id)

線程(線程[main,5,main]) - SELECT ID,employ_date,first_name,gender,last_name,matricule,phone_number,title,group_id FROM PERSON WHERE(group_id =? ) bind => [5302]

線程(線程[main,5,main]) - SELECT ID,employ_date,first_name,gender,last_name,matricule,phone_number,title,group_id FROM PERSON WHERE(group_id =? ) 綁定=> [6965]

線程(線程[主,5,主]) - (GROUP_ID =)SELECT ID,employ_date,如first_name,性別,姓氏,matricule,PHONE_NUMBER,標題,GROUP_ID FROM PERSON WHERE 綁定=> [6980]

線程(線程[主,5,主]) - (GROUP_ID =)SELECT ID,employ_date,如first_name,性別,姓氏,matricule,PHONE_NUMBER,標題,GROUP_ID FROM PERSON WHERE

回答

1

問題在於您的Person-> Group關係。它被標記爲渴望且沒有任何提取選項,強制爲從初始查詢中讀入的每個Person強制一個單獨的查詢。如上所述,將查詢標記爲使用加入或批量提取,或者使用您在Group-> Person關係中具有的相同或相似的OUTER選項將它們全部提取到單個查詢中。

更好的是,除非你真的需要在你的應用程序的每個部分中獲取的關係,否則不要太懶。

0

您在查詢中使用提取(以包含父Person實體的'group'子元素)。這是預期的行爲,因此您會遇到通常的N + 1 SQL SELECT問題。但是,由於您使用EclipseLink作爲JPA提供程序,因此可以執行優化,例如使用@JoinFetch@BatchFetch註釋(僅針對EclipseLink)。

查看這個link或查看EclipseLink文檔獲取更多信息。