2012-06-22 13 views
5

我的同事具有以下(顯然無效)JPQL查詢:在JPA 2.0 JPQL中,當返回一個NEW對象時,如何使用FETCH JOIN?

SELECT NEW com.foobar.jpa.DonationAllocationDTOEntity(a.id, a.campaign, a.campAppeal, a.campDivision, a.divisionFund) 
FROM DonationAllocation a JOIN a.donation d JOIN a.allocationType t 
JOIN FETCH a.campaign 
WHERE d.id = :donationId 
AND (t.code = 'Pledge' OR t.code = 'MatchingPledge') 

值得注意(供以後在該消息中),其DonationAllocation的與Campaign實體的關係是許多對一,並標記爲FetchType.LAZY。我的同事對這個查詢的意圖是(除其他外)確保a.campaign是「充氣」(急切地提取)。

休眠(顯然只是一個JPA實現的幾種),當面對這個查詢,說:

query specified join fetching, but the owner of the fetched association was not present in the select list

這是有道理的,因爲在選擇列表中只包含NEW DonationAllocationDTOEntity(),並且部分JPA 2.0規範的4.4.5.3規定:

FETCH JOIN子句右側引用的關聯必須是從實體引用的關聯或元素集合,或者是作爲查詢結果返回的可嵌入元素。

所以,因爲沒有「被返回作爲所述查詢的結果實體或嵌入」(這是一個DTO使用NEW操作者構造),接下去是沒有可能的關聯爲一個FETCH JOIN引用,因此這個查詢是無效的。

如何鑑於此限制,應該在這種情況下構建一個JPQL查詢,以便a.campaign - 被分配到構造函數表達式中?

回答

2

我會簡單地選擇實體及其關聯,然後直接調用結果來調用DTO構造函數。你將不得不編譯時檢查和refactorable代碼的額外好處:

select a from DonationAllocation a 
JOIN a.donation d 
JOIN a.allocationType t 
JOIN FETCH a.campaign 
WHERE d.id = :donationId 
AND (t.code = 'Pledge' OR t.code = 'MatchingPledge') 

... 

for (DonationAllocation a : list) { 
    result.add(new DonationAllocationDTOEntity(a.id, 
               a.campaign, 
               a.campAppeal, 
               a.campDivision, 
               a.divisionFund)); 
} 

編輯:

此查詢還應該選擇什麼需要,並避免選擇整個DonationAllocation實體:

select a.id, a.campaign, a.campAppeal, a.campDivision, a.divisionFund 
from DonationAllocation a 
JOIN a.donation d 
JOIN a.allocationType t 
WHERE d.id = :donationId 
AND (t.code = 'Pledge' OR t.code = 'MatchingPledge') 

,如果需要,您可以在查詢中添加DTO構造函數:

select new com.foobar.jpa.DonationAllocationDTOEntity(a.id, a.campaign, a.campAppeal, a.campDivision, a.divisionFund) 
from DonationAllocation a 
JOIN a.donation d 
JOIN a.allocationType t 
WHERE d.id = :donationId 
AND (t.code = 'Pledge' OR t.code = 'MatchingPledge') 

a.campaign在select子句中應該足以告訴Hibernate加載實體。至少這就是它在我的測試中的表現。

+0

謝謝。 'DonationAllocation'目前是一個巨大的對象,與EAGER關係太多。我相信我的同事正在試圖撤回它的某些部分。只是碰巧他所做的其中一個關係實際上是希望在這個查詢中加載。有了這些新知識,這會改變你的答案嗎? –

+0

是的,請參閱我的答案。但是如果加載實體就是這樣一個問題,那就意味着它的熱切關聯應該變得懶惰。我寧願讓一切都懶惰。 –

相關問題