स्प्रिंग डेटा और नेटिव क्वेरी पेजिंग के साथ


86

एक वेब प्रोजेक्ट में, MySQL 5.6 डेटाबेस के साथ नवीनतम स्प्रिंग-डेटा (1.10.2) का उपयोग करते हुए, मैं पेजेशन के साथ एक देशी क्वेरी का उपयोग करने की कोशिश कर रहा हूं, लेकिन मैं org.springframework.data.jpa.repository.query.InvalidJpaQueryMethodExceptionस्टार्टअप पर अनुभव कर रहा हूं ।

अद्यतन : 20180306 यह मुद्दा अब स्प्रिंग 2.0.4 में तय हो गया है। जो अभी भी रुचि रखते हैं या पुराने संस्करणों के साथ अटके हुए हैं, वे वर्कअराउंड के लिए संबंधित उत्तरों और टिप्पणियों की जांच करते हैं।

उदाहरण के अनुसार वसंत-डेटा प्रलेखन से @Query का उपयोग करते हुए यह क्वेरी को स्वयं निर्दिष्ट करना संभव है और इस तरह एक काउंटविक्यू:

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
}

जिज्ञासा से बाहर, NativeJpaQueryकक्षा में मैं देख सकता हूं कि यह जाँचने के लिए निम्नलिखित कोड है कि क्या यह एक वैध जप क्वेरी है:

public NativeJpaQuery(JpaQueryMethod method, EntityManager em, String queryString, EvaluationContextProvider evaluationContextProvider, SpelExpressionParser parser) {
   super(method, em, queryString, evaluationContextProvider, parser);
   JpaParameters parameters = method.getParameters();
   boolean hasPagingOrSortingParameter = parameters.hasPageableParameter() || parameters.hasSortParameter();
   boolean containsPageableOrSortInQueryExpression = queryString.contains("#pageable") || queryString.contains("#sort");
   if(hasPagingOrSortingParameter && !containsPageableOrSortInQueryExpression) {
       throw new InvalidJpaQueryMethodException("Cannot use native queries with dynamic sorting and/or pagination in method " + method);
   }
}

मेरी क्वेरी में एक Pageableपैरामीटर है, इसलिए hasPagingOrSortingParameterयह है true, लेकिन यह भी अंदर एक अनुक्रम #pageableया #sortअनुक्रम की तलाश में है queryString, जो मैं प्रदान नहीं करता हूं।

मैंने #pageableअपनी क्वेरी के अंत में जोड़ने की कोशिश की है (यह एक टिप्पणी है), जो पास करने के लिए सत्यापन करता है लेकिन फिर, यह निष्पादन में यह कहते हुए विफल हो जाता है कि क्वेरी 2 के बजाय एक अतिरिक्त पैरामीटर: 3 की अपेक्षा करती है।

अजीब बात यह है कि है, अगर मैं मैन्युअल रूप से बदल containsPageableOrSortInQueryExpressionसे falseकरने के लिए trueहै, जबकि चल रहा है, क्वेरी ठीक काम करता है तो मैं क्यों यह है कि स्ट्रिंग के लिए जाँच कर रहा है मेरी पर होना पता नहीं है queryStringऔर मैं नहीं जानता कि यह कैसे प्रदान करने के लिए।

कोई भी सहायताकाफी प्रशंसनीय होगी।

अद्यतन ०१/३०/२०१ 01 ऐसा लगता है कि वसंत-डेटा परियोजना के डेवलपर्स जेएनएन शाहर द्वारा पीआर के साथ इस मुद्दे के लिए एक तय पर काम कर रहे हैं


नहीं, मुझे अभी तक कोई समाधान नहीं मिला है। मैंने स्प्रिंग JIRA में एक टिकट बनाया, लेकिन कोई प्रतिक्रिया नहीं मिली: jira.spring.io/browse/DATAJPA-928 । अंत में, मुझे पेजिंग की ज़रूरत नहीं थी इसलिए मैंने किसी भी तरह की जाँच करने या उस टिकट के साथ कड़ी मेहनत करने की कोशिश नहीं की।
लसनीक्स

3
ठीक है शुक्रिया। एक वर्कअराउंड के रूप में आप "#pageable" के बजाय "\ n # pageable \ n" जोड़ सकते थे, लेकिन मुझे उम्मीद है कि यह भविष्य में तय हो जाएगा।
जनार

1
उस मौजूदा फिक्स ने मेरे लिए चीजों को बदतर बना दिया। अब मेरा पेजएबल पैरामीटर पूरी तरह से नजरअंदाज कर दिया गया है और क्वेरी असीमित निष्पादित की गई है। इसलिए यदि आपने वह \ n # पैगवेबल \ n वर्कअराउंड डाला है, तो इसे निकालना सुनिश्चित करें या आप परेशानी में पड़ जाएंगे।
रुडिगर शूल्ज

जवाबों:


48

अग्रिम में मेरी क्षमा याचना, यह मूल प्रश्न और जनर की टिप्पणी से बहुत अधिक है , हालांकि ...

मैं एक ही समस्या में भाग लेता हूं: मैंने उदाहरण के तौर पर स्प्रिंग डेटा का उदाहरण 50 पाया, जिसमें पेजेशन के साथ एक देशी क्वेरी होने की आवश्यकता थी, लेकिन स्प्रिंग स्टार्टअप पर शिकायत कर रहा था कि मैं मूल प्रश्नों के साथ पेजेशन का उपयोग नहीं कर सकता।

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

    @Query(value="SELECT a.* "
            + "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
            + "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time)"
            + "ORDER BY a.id \n#pageable\n", 
        /*countQuery="SELECT count(a.*) "
            + "FROM author a left outer join mappable_natural_person p on a.id = p.provenance_id "
            + "WHERE p.update_time is null OR (p.provenance_name='biblio_db' and a.update_time>p.update_time) \n#pageable\n",*/
        nativeQuery=true)
public List<Author> findAuthorsUpdatedAndNew(Pageable pageable);

गणक (जो कि कोड ब्लॉक में टिप्पणी की गई है) को Page<Author> क्वेरी के रिटर्न प्रकार के रूप में उपयोग करने की आवश्यकता है , अपेक्षित मापदंडों की संख्या पर रनटाइम त्रुटि से बचने के लिए "#pageable" टिप्पणी के आसपास की नई रूपरेखाओं की आवश्यकता है। समाधान)। मुझे उम्मीद है कि यह बग जल्द ही ठीक हो जाएगा ...


1
मेरे मामले ?#{#pageable}में इसके बजाय काम कर रहा है \n#pageable\n
दिमित्री स्टोलबोव

6
यह काम। तर्कों के लिए आप अभी भी नामित मापदंडों का उपयोग कर सकते हैं। उदाहरण है :authorId। मैं अपने बदल \n#pageable\nकरने के लिए --#pageable\nPostgreSQL के लिए। जब आप कई उदाहरणों की सूची का उपयोग करते हैं, तो आपको गिनने की आवश्यकता होती है क्योंकि पेज <> के बजाय सूची <> आपका जवाब इसके लिए हाजिर था। मैं उसी डॉक्स से गुज़रा और अगर यह आपके जवाब के लिए नहीं होता तो मैं बस छोड़ देता।
अभिषेक दुजारी

2
यदि आप countQuery नहीं लिखते हैं और फ्रेमवर्क को हैंडल करते हैं, तो कुछ समय आपके लिए क्वेरी द्वारा गिनती सही से नहीं लिखता है और आपको अमान्य फ़ील्ड सूची के रूप में एक त्रुटि दिखाई दे सकती है। संपत्ति फ़ाइल लॉगिंग में नीचे प्रविष्टियों को जोड़कर आप हमेशा SQL कथनों का विश्लेषण कर सकते हैं। समस्या ठीक करें। यह फ्रेमवर्क संस्करणों और आपके द्वारा उपयोग किए जा रहे डेटाबेस पर निर्भर हो सकता है।
नालाका

मेरे मामले में केवल /*:pageable*/एसक्यूएल सर्वर, हाइबरनेट 5.4.1.फाइनल और स्प्रिंग बूट 2.2.1 के साथ काम करता है
9

35

यह संस्करण 2.0.4 से पहले स्प्रिंग डेटा जेपीए का उपयोग करके प्रोग्राम के लिए हैक है ।

कोड ने PostgreSQL और MySQL के साथ काम किया है:

public interface UserRepository extends JpaRepository<User, Long> {

@Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY ?#{#pageable}",
       countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
       nativeQuery = true)
   Page<User> findByLastname(String lastname, Pageable pageable);   
}

ORDER BY ?#{#pageable}के लिए है PageablecountQueryके लिए है Page<User>


1
मैं नहीं जानता हूँ। 1. SQL कथन की लॉगिंग सक्षम का प्रयास करें - सेट spring.jpa.show-sql=falseमें application.properties; 2. ?#{#pageable}अपने नेटवर्क्स में सेट करें और 3. लॉग से SQL परिणाम का विश्लेषण करें। @Lasneyx ने स्प्रिंग डेटा JPA की इस ख़ासियत के लिए DATAJPA-928 को मुद्दा बनाया ।
दिमित्री स्टोलबोव

12

सिर्फ रिकॉर्ड के लिए, परीक्षण डेटाबेस के रूप में H2 और रनटाइम पर MySQL का उपयोग करते हुए, यह दृष्टिकोण काम करता है (उदाहरण समूह में नवीनतम ऑब्जेक्ट है :

@Query(value = "SELECT t.* FROM t LEFT JOIN t AS t_newer " +
        "ON t.object_id = t_newer.object_id AND t.id < t_newer.id AND o_newer.user_id IN (:user_ids) " +
        "WHERE t_newer.id IS NULL AND t.user_id IN (:user_ids) " +
        "ORDER BY t.id DESC \n-- #pageable\n",
        countQuery = "SELECT COUNT(1) FROM t WHERE t.user_id IN (:user_ids) GROUP BY t.object_id, t.user_id",
        nativeQuery = true)
Page<T> findByUserIdInGroupByObjectId(@Param("user_ids") Set<Integer> userIds, Pageable pageable);

स्प्रिंग डेटा JPA 1.10.5, H2 1.4.194, MySQL सामुदायिक सर्वर 5.7.11-लॉग (innodb_version 5.7.11)।


PostgreSQL के लिए काम किया। धन्यवाद!
मैक्सीम चेर्निकोव

क्या होगा यदि हमें क्वेरी में गतिशील रूप से asc या desc द्वारा ऑर्डर पास करना है?
कुलभूषण सिंह

8

मेरे पास @Lasneyx जैसा ही लक्षण है। देशी क्वेरी पोस्टग्रैज के लिए मेरा वर्कअराउंड

@Query(value = "select * from users where user_type in (:userTypes) and user_context='abc'--#pageable\n", nativeQuery = true)
List<User> getUsersByTypes(@Param("userTypes") List<String> userTypes, Pageable pageable);

मेरे लिए DB2 के साथ भी काम किया।
एंडर्स मेटनिक

@Query (nativeQuery = true, value = "a चुनें। * A rqst from a LEFT OUTER JOIN table_b b ON a.id = b.id जहां a .code = 'abc' ORDER BY - # pageable's n") नहीं है कार्य करना: $ 2
डेवलपर

7

इसे इस्तेमाल करे:

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 ORDER BY /*#pageable*/",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
}

("/* */" लिए Oracle notation)


किसी कारण से उत्पन्न क्वेरी कॉमा के पास होने के बाद कुछ इस तरह से "ORDER BY / * # pageable * /," वाक्यविन्यास त्रुटि का कारण बनती है
d-man

मैं आदेश को हटा देता हूं, लेकिन अपवादित अनपेक्षित चार: '#'
हिचम एब्डैमाइम

5

मैं ओरेकल डेटाबेस का उपयोग करता हूं और मुझे परिणाम नहीं मिला लेकिन उत्पन्न अल्पविराम के साथ एक त्रुटि जो डी-मैन ऊपर के बारे में बोलते हैं।

तब मेरा समाधान था:

Pageable pageable = new PageRequest(current, rowCount);

जब आप Pagable बनाते समय बिना आदेश के देख सकते हैं।

और डीएओ में विधि:

public interface UserRepository extends JpaRepository<User, Long> {
  @Query(value = "SELECT * FROM USERS WHERE LASTNAME = ?1 /*#pageable*/ ORDER BY LASTNAME",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
  Page<User> findByLastname(String lastname, Pageable pageable);
 }

1

निम्नलिखित दोनों दृष्टिकोण देशी क्वेरी को पृष्ठांकित करने के लिए MySQL के साथ ठीक काम करते हैं। हालांकि वे H2 के साथ काम नहीं करते हैं। यह sql सिंटैक्स त्रुटि की शिकायत करेगा।

  • आदेश द्वारा
  • ORDER BY a.id \ n # pageable \ n


1

मैं पेजिनेशन को सफलतापूर्वक एकीकृत कर सकता हूं

वसंत-डेटा-जपा-2.1.6

निम्नलिखित नुसार।

@Query(
 value = “SELECT * FROM Users”, 
 countQuery = “SELECT count(*) FROM Users”, 
 nativeQuery = true)
Page<User> findAllUsersWithPagination(Pageable pageable);

0

यह नीचे के रूप में काम करता है:

public interface UserRepository extends JpaRepository<User, Long> {
    @Query(value = "select * from (select (@rowid\\:=@rowid+1) as RN, u.* from USERS u, (SELECT @rowid\\:=0) as init where  LASTNAME = ?1) as total"+
        "where RN between ?#{#pageable.offset-1} and ?#{#pageable.offset + #pageable.pageSize}",
    countQuery = "SELECT count(*) FROM USERS WHERE LASTNAME = ?1",
    nativeQuery = true)
    Page<User> findByLastname(String lastname, Pageable pageable);
}

0

मेरे लिए नीचे MS SQL में काम किया है

 @Query(value="SELECT * FROM ABC r where r.type in :type  ORDER BY RAND() \n-- #pageable\n ",nativeQuery = true)
List<ABC> findByBinUseFAndRgtnType(@Param("type") List<Byte>type,Pageable pageable);

0

मैं नीचे दिए गए कोड का उपयोग कर रहा हूं। काम कर रहे

@Query(value = "select * from user usr" +
  "left join apl apl on usr.user_id = apl.id" +
  "left join lang on lang.role_id = usr.role_id" +
  "where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds ORDER BY ?#{#pageable}",
  countQuery = "select count(*) from user usr" +
      "left join apl apl on usr.user_id = apl.id" +
      "left join lang on lang.role_id = usr.role_id" +
      "where apl.scr_name like %:scrname% and apl.uname like %:uname and usr.role_id in :roleIds",
  nativeQuery = true)
Page<AplUserEntity> searchUser(@Param("scrname") String scrname,@Param("uname") String  uname,@Param("roleIds") List<Long> roleIds,Pageable pageable);

1
कृपया आप यह बता सकते हैं कि यह उत्तर अन्य वर्षों की तुलना में बेहतर क्यों है?
खींचें

0

क्वेरी और गणना क्वेरी दोनों से \ n # pageable \ n को हटाना मेरे लिए काम किया। स्प्रिंगबूट संस्करण: 2.1.5


0

इसने मेरे लिए काम किया (मैं पोस्टग्रोज़ का उपयोग कर रहा हूं) ग्रूवी में:

@RestResource(path="namespaceAndNameAndRawStateContainsMostRecentVersion", rel="namespaceAndNameAndRawStateContainsMostRecentVersion")
    @Query(nativeQuery=true,
            countQuery="""
            SELECT COUNT(1) 
            FROM 
            (
                SELECT
                ROW_NUMBER() OVER (
                    PARTITION BY name, provider_id, state
                    ORDER BY version DESC) version_partition,
                *
                FROM mydb.mytable
                WHERE
                (name ILIKE ('%' || :name || '%') OR (:name = '')) AND
                (namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND
                (state = :state OR (:state = ''))
            ) t
            WHERE version_partition = 1
            """,
            value="""
            SELECT id, version, state, name, internal_name, namespace, provider_id, config, create_date, update_date 
            FROM 
            (
                SELECT 
                ROW_NUMBER() OVER (
                    PARTITION BY name, provider_id, state
                    ORDER BY version DESC) version_partition,
                *
                FROM mydb.mytable
                WHERE 
                (name ILIKE ('%' || :name || '%') OR (:name = '')) AND
                (namespace ILIKE ('%' || :namespace || '%') OR (:namespace = '')) AND
                (state = :state OR (:state = ''))       
            ) t            
            WHERE version_partition = 1             
            /*#{#pageable}*/
            """)
    public Page<Entity> findByNamespaceContainsAndNameContainsAndRawStateContainsMostRecentVersion(@Param("namespace")String namespace, @Param("name")String name, @Param("state")String state, Pageable pageable)

यहाँ कुंजी का उपयोग करना था: /*#{#pageable}*/

यह मुझे सॉर्टिंग और पेजिंग करने की अनुमति देता है। आप इसे कुछ इस तरह से उपयोग करके इसका परीक्षण कर सकते हैं: http: // localhost: 8080 / api / v1 / संस्थाओं / खोज / namepace

इस समस्या के लिए देखें: स्प्रिंग पेजेबल @Column नाम का अनुवाद नहीं करता है


0

आप h2 और MySQl के लिए नीचे दिए गए कोड का उपयोग कर सकते हैं

    @Query(value = "SELECT req.CREATED_AT createdAt, req.CREATED_BY createdBy,req.APP_ID appId,req.NOTE_ID noteId,req.MODEL model FROM SUMBITED_REQUESTS  req inner join NOTE note where req.NOTE_ID=note.ID and note.CREATED_BY= :userId "
        ,
         countQuery = "SELECT count(*) FROM SUMBITED_REQUESTS req inner join NOTE note WHERE req.NOTE_ID=note.ID and note.CREATED_BY=:userId",
        nativeQuery = true)
Page<UserRequestsDataMapper> getAllRequestForCreator(@Param("userId") String userId,Pageable pageable);

-1

प्रतिस्थापित करना / #pageable / के साथ? पेजेबलडबल्ट जोड़ने से आप पेज एलिमेंट्स का साइज सेट कर सकते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.