2012-06-22 7 views
5

Benim bir meslektaşım (görünüşte geçersiz) JPQL sorgusu aşağıdaki etti:JPA 2.0 JPQL'de, bir YENİ nesneyi döndürdüğünde, FETCH JOIN'leri nasıl kullanabilir?

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') 

Bir Campaign varlık ile DonationAllocation 'ın göre bu ilişki bire olduğu (bu mesajın devamında için) dikkati çekiyor, ve FetchType.LAZY olarak işaretlenmiştir. Meslektaşımın bu sorgunun amacı, (diğer şeylerin yanı sıra) a.campaign'un "şişirilmiş" (hevesle getirilmiş) olduğunu garanti etmektir. Seçim listesi yalnızca NEW DonationAllocationDTOEntity() içerdiğinden

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

Bu, mantıklı ve bölüm:

Hazırda (birkaçının besbelli sadece bir JPA uygulaması), bu sorgu ile karşılaştığında, diyor JPA 2.0 belirtiminin 4.4.5.3'ü:

FETCH JOIN yan tümcesinin sağ tarafından başvurulan ilişkilendirme Bir kuruluştan başvurulan bir ilişki veya öğe koleksiyonu veya sorgunun sonucu olarak döndürülen gömülebilir olabilir.

Yani "terimi bir sonucu olarak döndürülür antite gömülebilir" olduğundan (o bir DTO NEW operatörü kullanılarak oluşturulan), bir referans artır FETCH için olası bir ilişki olduğunu aşağıdaki ve dolayısıyla bu sorgu geçersiz.

Bu sınırlama dikkate alındığında, bu durumda, bir JPQL sorgusu, yapıcı ifadesine girilen a.campaign - hevesle getirilecek şekilde nasıl oluşturulur?

cevap

2

Sadece varlığı ve ilişkilendirmesini seçer ve DTO yapıcısını açıkça çağırmak için sonuçları yanıtlar. Sen derleme zamanı kontrol ve refactorable ek kod avantajına sahip olacaktır:

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)); 
} 

DÜZENLEME:

da gerekenden seçin ve bütün DonationAllocation varlığı seçilirken kaçınmalıdır Bu sorgu:

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') 

ve sadece isterseniz sorguda DTO yapıcısı ekleyebiliriz:

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'ın select yan tümcesinde olması gerçeği, Hazırda bekletme nesnesini yüklemeye bildirmek için yeterli olmalıdır. En azından testlerimde böyle davranıyor.

+0

Teşekkür ederiz. 'DonationAllocation' şu anda çok fazla sayıda "EAGER" ilişkisi olan bir * büyük * nesnesidir. İş arkadaşımın sadece belirli kısımlarını geri çekmeye çalıştığına inanıyorum. Öyle ki, bu ilişkilerden biri, aslında bu sorguda hevesle yüklenmesini istemektedir. Bu yeni bilgi ile cevabınızı değiştirir mi? –

+0

Evet, cevabımı görün. Fakat eğer varlığın yüklenmesi böyle bir problemse, bu sadece istekli derneklerinin tembel olması gerektiği anlamına gelir. Her şeyi tembelleştirmeyi tercih ederim. –

İlgili konular