2012-06-14 22 views
14

मैं पहले से ही निम्नलिखित कोड का उपयोग कर पृष्ठांकन को लागू किया है किया है:हाइबरनेट मानदंड के साथ पृष्ठांकन और DISTINCT_ROOT_ENTITY

public Paginacao<Anuncio> consultarPaginado(int pagina, Integer cidadeId) { 

      Criteria criteria = this.sessionFactory.getCurrentSession().createCriteria(Anuncio.class);  
      criteria.add(Restrictions.eq("ativo", true)); 
      criteria.add(Restrictions.eq("statusLiberacao", AnunciosUtil.STATUS_ANUNCIO_LIBERADO)); 
      criteria.add(Restrictions.eq("statusVendaAnuncio", AnunciosUtil.STATUS_VENDA_ANUNCIO_DISPONIVEL)); 

      if (cidadeId != null) { 
       criteria.add(Restrictions.eq("cidade.id", cidadeId)); 
      } 

      criteria.addOrder(Order.desc("dataPostagem")); 
      criteria.setProjection(Projections.rowCount()); 

      Long count = (Long) criteria.uniqueResult(); 

      Paginacao<Anuncio> paginacao = new Paginacao<Anuncio>(); 
      int qtdPaginas = (count.intValue()/7) + 1; 

      paginacao.setQtdPaginas(qtdPaginas); 

      criteria.setProjection(null);// reseta a criteria sem a projeção 
      criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

      if (pagina > qtdPaginas) { 
       pagina = qtdPaginas; 
      } 
      pagina = pagina - 1; 
      criteria.setFirstResult(pagina * ConstantesGenericas.MAXIMO_OBJETOS_RETORNADOS); 
      criteria.setMaxResults(ConstantesGenericas.MAXIMO_OBJETOS_RETORNADOS); 

      paginacao.setRegistros(criteria.list()); 

      return paginacao; 
     } 

जब मैं SQL क्वेरी मैन्युअल रूप से बनाने और डेटाबेस में जमा करें, मैं 8 परिणाम नहीं। हालांकि, जब मैं उपरोक्त कोड आज़माता हूं, तो परिणाम ट्रान्सफॉर्मर को DISTINCT_ROOT_ENTITY पर सेट करने से पहले 8 परिणाम प्राप्त करें (बिना विशिष्ट के) और इसे सेट करने के बाद मुझे 4 परिणाम मिलते हैं। लेकिन मुझे 8 परिणाम प्राप्त करना चाहिए (DISTINCT का उपयोग करके), क्योंकि जब मैं बिना किसी भिन्न के मैन्युअल रूप से एसक्यूएल बनाता हूं तो मुझे 11 परिणाम मिलते हैं और जब मैं DISTINCT का उपयोग करता हूं तो मुझे सही तरीके से मिलता है, 8 परिणाम परिणाम देते हैं।

उपरोक्त कोड में क्या गलत है?

उत्तर

23

मेरी समस्या के लिए समाधान की तलाश में लंबे समय बाद मैंने इसे हल करने में कामयाब रहे। समस्या यह है कि यदि आप जॉइन और का उपयोग करके कई संगठनों को पुनर्प्राप्त करने वाले मानदंड या क्वेरी बनाते हैं तो आप setMaxResults का उपयोग करते हैं और परिणाम ट्रान्सफ़ॉर्मर को DISTINCT_ROOT_ENTITY पर सेट करते हैं, परिणाम आपको अपेक्षित नहीं होगा।

के रूप में जेबी Nizet कहा, तुम 4 ए संस्थाओं, 3 बी संस्थाओं के साथ प्रत्येक है लगता है, और आपकी जिज्ञासा उनके बी एस के साथ सभी एक संस्थाओं को पुन: प्राप्त लगता है।

उस स्थिति में, SQL क्वेरी 12 पंक्तियों को वापस कर देगी। यदि आप setMaxResults (7) का उपयोग करते हैं, तो यह ए 1 और उसके बीएस के लिए तीन पंक्तियां, ए 2 और उसके बीएस के लिए तीन पंक्तियां और ए 3 के लिए केवल 1 पंक्ति और उसके पहले बी

और आपके पास DISTINCT_ROOT_ENTITY का उपयोग किया गया, मानदंड क्वेरी केवल तीन इकाइयों को वापस लाएगी: ए 1, ए 2, और ए 3 (जिसमें बीएस का अपूर्ण सेट होगा)।

इस का समाधान करने के लिए आप चुन सकते हैं या सबसिलेक्ट को toMany (आमतौर पर संग्रह) रिश्तों के लिए लाने मोड सेट करने के लिए है, और आप इस लक्ष्य को हासिल करने के लिए मूल रूप से 2 तरीके हैं:

पहले तरीके से उपयोग करने @FetchMode (है FetchMode.SUBSELECT) आपकी विशेषता पर एनोटेशन, और मुझे यह दृष्टिकोण पसंद नहीं है क्योंकि यह संग्रह को पुनर्प्राप्त करने के लिए प्रत्येक क्वेरी को SUBSELECT FETCH का उपयोग करने का कारण बनता है। लेकिन यह काम करेगा।

दूसरा तरीका है जब आप अपनी क्वेरी बनाते हैं तो संबंधों के लिए रिच मोड सेट करना है। मैं इस तरह से पसंद करता हूं, क्योंकि मैं अपनी जरूरतों के लिए क्वेरी को कस्टमाइज़ कर सकता हूं और मुझे सभी प्रश्नों के लिए SUBSELECTS का उपयोग करने की आवश्यकता नहीं है। इसलिए, मैंने यह तरीका किया है:

public Paginacao<Anuncio> consultarPaginado(int pagina, Integer cidadeId) { 

     Criteria criteria = this.sessionFactory.getCurrentSession().createCriteria(Anuncio.class);  
     criteria.add(Restrictions.eq("ativo", true)); 
     criteria.add(Restrictions.eq("statusLiberacao", AnunciosUtil.STATUS_ANUNCIO_LIBERADO)); 
     criteria.add(Restrictions.eq("statusVendaAnuncio", AnunciosUtil.STATUS_VENDA_ANUNCIO_DISPONIVEL)); 
     criteria.setFetchMode("imagens", FetchMode.SELECT); 
     criteria.setFetchMode("pagamentos", FetchMode.SELECT);  

     if (cidadeId != null) { 
      criteria.add(Restrictions.eq("cidade.id", cidadeId)); 
     } 

     criteria.addOrder(Order.desc("dataPostagem")); 
     criteria.setProjection(Projections.rowCount()); 

     Long count = (Long) criteria.uniqueResult(); 

     Paginacao<Anuncio> paginacao = new Paginacao<Anuncio>(); 
     int qtdPaginas = (count.intValue()/7) + 1; 

     paginacao.setQtdPaginas(qtdPaginas); 

     criteria.setProjection(null);// reseta a criteria sem a projeção 
     criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

     if (pagina > qtdPaginas) { 
      pagina = qtdPaginas; 
     } 
     pagina = pagina - 1; 
     criteria.setFirstResult(pagina * ConstantesGenericas.MAXIMO_OBJETOS_RETORNADOS); 
     criteria.setMaxResults(ConstantesGenericas.MAXIMO_OBJETOS_RETORNADOS); 

     paginacao.setRegistros(criteria.list()); 

     return paginacao; 
    } 

आशा है कि यह किसी और की सहायता करे। ; D

+8

मैं गंभीरता से इच्छा अपने चर नाम अभी भी पुर्तगाली :) –

+0

में नहीं थे यह काम नहीं कर सकते .. सभी * ToMany संग्रह FetchMode.SELECT जोड़ने की कोशिश की, लेकिन अभी भी परिणाम के बिना .. – nKognito

+0

धन्यवाद! यह न केवल मेरे लिए काम करता है बल्कि मैं कुछ दिनों के लिए समाधान की तलाश में हूं। आपको समाधान और स्पष्टीकरण मिला! मुझे वास्तव में वास्तव में यह पोस्ट पसंद आया !!! – Alexandros

13

मुझे यकीन है कि अगर मैं अपने प्रश्न सही ढंग से समझ नहीं कर रहा हूँ, लेकिन अगर आपकी क्वेरी को पुन: प्राप्त toMany संघों के साथ संस्थाओं में शामिल होने से प्राप्त किए गए, तो पृष्ठांकन अपेक्षा के अनुरूप काम नहीं होगा।

दरअसल, आप 4 ए संस्थाओं, 3 बी संस्थाओं के साथ प्रत्येक है लगता है, और आपकी जिज्ञासा उनके बी एस के साथ सभी एक संस्थाओं को पुन: प्राप्त लगता है।

उस स्थिति में, SQL क्वेरी 12 पंक्तियों को वापस कर देगी। यदि आप setMaxResults (7) का उपयोग करते हैं, तो यह ए 1 और उसके बीएस के लिए तीन पंक्तियां, ए 2 और उसके बीएस के लिए तीन पंक्तियां और ए 3 के लिए केवल 1 पंक्ति और उसके पहले बी

और आपके पास DISTINCT_ROOT_ENTITY का उपयोग किया गया, मानदंड क्वेरी केवल तीन इकाइयों को वापस लाएगी: ए 1, ए 2, और ए 3 (जिसमें बीएस का अपूर्ण सेट होगा)।

+1

हाँ, मैं समझ गया मैं पहले से ही इसे हल कर दिया है। चींटी यह ठीक है जैसा आपने कहा था। मैं जवाब पोस्ट करूंगा। – jguilhermemv

9

यह मेरे लिए एक मुद्दा था, और यह कुछ समय के लिए एक समाधान है कि मैं सभी परिदृश्यों के लिए काम करता है साथ आने के लिए ले लिया।

आप प्रत्येक पृष्ठांकन पेज के लिए क्या चाहिए 2 बातें, सभी परिणामों की कुल संख्या और परिणामों का एक पृष्ठ है, लेकिन है कि आप 3 कदम उठाने की आवश्यकता नहीं है। 1) कुल गिनती प्राप्त करें, 2) अपने पृष्ठ के लिए अद्वितीय आईडी प्राप्त करें, और 3) चरण 2 में पाए गए आईडी के लिए पूरा डेटा प्राप्त करें। और आप एक ही मानदंड वस्तु के साथ ऐसा कर सकते हैं:

1) , कुल संख्या प्राप्त विशिष्ट आईडी का उपयोग कर (uniqueField इकाई कक्षा में अपनी पहचान के नाम =)

Criteria criteria = session.createCriteria(YourEntity.class); 
    Projection idCountProjection = Projections.countDistinct(uniqueField); 
    criteria.setProjection(idCountProjection); 
    //setup criteria, joins etc here 
    int totalResultCount = ((Long)criteria.uniqueResult()).intValue(); 

2) प्रक्षेपण रीसेट और आरंभ और लंबाई सेट (आप अलग आईडी चाहते हैं)

criteria.setProjection(Projections.distinct(Projections.property(uniqueField))); 
    criteria.setFirstResult(start); 
    criteria.setMaxResults(length); 
    List uniqueSubList = criteria.list(); 

3) प्रक्षेपण रीसेट और अलग परिणाम है कि आईडी से मेल प्राप्त

criteria.setProjection(null); 
    criteria.setFirstResult(0); criteria.setMaxResults(Integer.MAX_VALUE); 
    criteria.add(Restrictions.in(uniqueField, uniqueSubList)); 
    criteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 
    List searchResults = criteria.list(); 
    //and now, however you want to return your results 
    Map<String, Object> searchResultsMap = new HashMap<String, Object>(); 
    searchResultsMap.put("searchResults", searchResults); 
    searchResultsMap.put("totalResultCount", totalResultCount); 
+0

यह बहुत अच्छा है! एक टिप्पणी हालांकि: यदि आप कुछ डेटाबेस से आदेश का उपयोग क्रम कॉलम के आधार पर परिणाम दूसरी क्वेरी के लिए सेट का हिस्सा बनने की आवश्यकता है। एक उदाहरण के लिए http://www.h2database.com/javadoc/org/h2/constant/ErrorCode.html#c90068 देखें। – jontejj

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