2015-03-26 11 views
9

का उपयोग करते हुए खंड मैं क्लियर डीएसएल का उपयोग करने के लिए एक पॉलीमोर्फिक के साथ एक प्रश्न लिखने की कोशिश कर रहा हूं जहां खंड।पॉलिमॉर्फिक जहां क्वार्टर डीएस

चूंकि मैं सारणी में क्या करना चाहता हूं, यह समझाने में थोड़ा मुश्किल है, मैं cloned the spring-boot-sample-data-jpa project और इसे जो करने की कोशिश कर रहा हूं उसका एक उदाहरण दिखाने के लिए संशोधित किया गया है।

मैं these model classes, तुम कहाँ ध्यान दें जाएगा कि SpaHotel और SportHotelHotel इकाई का विस्तार किया है।

मैं एक प्रश्न लिखने की कोशिश कर रहा हूं जो SpaHotel, या SportHotel युक्त सभी शहरों को लौटाता है जिसका मुख्य खेल दिए गए प्रकार का है।

मैं एक JPQL version of that query है, जो एक छोटे से बदसूरत है लिखा था (मैं sport is null हिस्सा दर्शाता है कि यह एक स्पा होटल है पसंद नहीं है), लेकिन मैं क्या चाहते हैं वापस जाने के लिए लगता है।

लेकिन the QueryDsl version of that query काम करने के लिए प्रतीत नहीं होता:

public List<City> findAllCitiesWithSpaOrSportHotelQueryDsl(SportType sportType) { 
    QCity city = QCity.city; 
    QHotel hotel = QHotel.hotel; 

    return queryFactory.from(city) 
     .join(city.hotels, hotel) 
     .where(
      hotel.instanceOf(SpaHotel.class).or(
       hotel.as(QSportHotel.class).mainSport.type.eq(sportType) 
     ) 
    ).list(city); 
} 

मेरे test के साथ विफल:

test_findAllCitiesWithSpaOrSportHotelQueryDsl(sample.data.jpa.service.CityRepositoryIntegrationTests) Time elapsed: 0.082 sec <<< FAILURE! 
java.lang.AssertionError: 
Expected: iterable over [<Montreal,Canada>, <Aspen,United States>, <'Neuchatel','Switzerland'>] in any order 
    but: No item matches: <Montreal,Canada> in [<Aspen,United States>, <'Neuchatel','Switzerland'>] 
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:20) 
    at org.hamcrest.MatcherAssert.assertThat(MatcherAssert.java:8) 
    at sample.data.jpa.service.CityRepositoryIntegrationTests.test_findAllCitiesWithSpaOrSportHotelQueryDsl(CityRepositoryIntegrationTests.java:95) 

यह मेरी क्वेरी की तरह लगता है वापस नहीं करता है "मॉन्ट्रियल" है, जो वापस आ जाना चाहिए, चूंकि इसमें स्पाहोटल है।

इसके अलावा, मुझे आश्चर्य है कि अगर यह सामान्य है कि QueryDsl एक क्रॉस में मेरी क्वेरी का अनुवाद होगा शामिल हो:

select city0_.id as id1_0_, city0_.country as country2_0_, city0_.name as name3_0_ 
from city city0_ 
inner join hotel hotels1_ 
on city0_.id=hotels1_.city_id 
cross join sport sport2_ 
where hotels1_.main_sport_id=sport2_.id and (hotels1_.type=? or sport2_.type=?) 

मेरे सवालों का:

  1. वापस नहीं "मॉन्ट्रियल" है, जो होता है, जो क्वेरी क्यों है SpaHotel?
  2. क्या यह प्रश्न लिखने का कोई बेहतर तरीका है?
  3. क्या यह सामान्य है कि उत्पन्न SQL एक क्रॉस-जॉइन करता है? क्या हम जेपीक्यूएल में जैसे बाएं-जॉइन नहीं कर सकते हैं?

उत्तर

3

अपने JPQL क्वेरी का सही परिवर्तन

String jpql = "select c from City c" 
    + " join c.hotels hotel" 
    + " left join hotel.mainSport sport" 
    + " where (sport is null or sport.type = :sportType)"; 

return queryFactory.from(city) 
    .join(city.hotels, hotel) 
    .leftJoin(hotel.as(QSportHotel.class).mainSport, sport) 
    .where(sport.isNull().or(sport.type.eq(sportType))) 
    .list(city); 

आपकी मूल क्वेरी में इस संपत्ति के उपयोग

hotel.as(QSportHotel.class).mainSport 

पार में शामिल होने का कारण बनता है और बाधाओं क्वेरी है SportHotels के लिए।

क्वेरीरीडल केवल उन पथों के लिए अंतर्निहित बाएं जुड़ता है जो केवल क्रम में उपयोग किए जाते हैं, क्वेरी का हिस्सा, सबकुछ अंतर्निहित आंतरिक जुड़ता है।

+0

बहुत रोचक, मुझे एहसास नहीं हुआ कि आप एक उप प्रकार के पथ को कास्ट करने के लिए 'leftJoin()' में 'as()' का उपयोग कर सकते हैं। यह मेरी समस्या पूरी तरह से हल करता है। तेज़ उत्तर के लिए और QueryDsl के विकास के लिए बहुत बहुत धन्यवाद। यह विस्मयकारी है। –

संबंधित मुद्दे