वसंत-डाटा-जेपीए एनोटेशन के लिए setMaxResults?


127

मैं अपने प्रोजेक्ट में स्प्रिंग-डेटा-जेपीए को शामिल करने की कोशिश कर रहा हूं। एक बात जो मुझे भ्रमित करती है कि मैं एनोटेशन द्वारा setMaxResults (n) कैसे प्राप्त करूं?

उदाहरण के लिए, मेरा कोड:

public interface UserRepository extends CrudRepository<User , Long>
{
  @Query(value="From User u where u.otherObj = ?1 ")
  public User findByOhterObj(OtherObj otherObj);
}

मुझे केवल one (and only one)अन्य ओओबीजे से उपयोगकर्ता को वापस करने की आवश्यकता है , लेकिन मुझे अधिकतम एनोटेट को एनोटेट करने का कोई तरीका नहीं मिल सकता है। क्या कोई मुझे संकेत दे सकता है?

(mysql शिकायत:

com.mysql.jdbc.JDBC4PreparedStatement@5add5415: select user0_.id as id100_, user0_.created as created100_ from User user0_ where user0_.id=2 limit ** NOT SPECIFIED **
WARN  util.JDBCExceptionReporter - SQL Error: 0, SQLState: 07001
ERROR util.JDBCExceptionReporter - No value specified for parameter 2

)

मुझे एक लिंक मिला: https://jira.springsource.org/browse/DATAJPA-147 , मैंने कोशिश की लेकिन असफल रहा। यह अब संभव नहीं लगता? इस तरह के एक महत्वपूर्ण विशेषता को स्प्रिंग-डेटा में क्यों नहीं बनाया गया है?

यदि मैं इस सुविधा को मैन्युअल रूप से लागू करता हूं:

public class UserRepositoryImpl implements UserRepository

मुझे पूर्वनिर्धारित तरीकों के टन को लागू CrudRepositoryकरना होगा, यह भयानक होगा।

वातावरण: वसंत-3.1, वसंत-डेटा-जपा-1.0.3.RELEASE.jar, वसंत-डेटा-कॉमन्स-कोर-1.1.0.ELEASE.jar

जवाबों:


176

स्प्रिंग डेटा जेपीए 1.7.0 (इवांस रिलीज़ ट्रेन) के रूप में।

आप नए शुरू किए गए Topऔर Firstकीवर्ड का उपयोग कर सकते हैं जो आपको क्वेरी विधियों को इस तरह परिभाषित करने की अनुमति देते हैं:

findTop10ByLastnameOrderByFirstnameAsc(String lastname);

स्प्रिंग डेटा स्वचालित रूप से आपके द्वारा परिभाषित संख्या तक परिणामों को सीमित कर देगा (चूक होने पर 1 पर डिफ़ॉल्ट)। ध्यान दें कि परिणामों का क्रम यहां प्रासंगिक हो जाता है (या तो OrderByउदाहरण के अनुसार एक खंड के माध्यम से या एक Sortपैरामीटर को विधि में सौंपकर )। स्प्रिंग डेटा इवांस रिलीज ट्रेन या प्रलेखन में नई सुविधाओं को कवर करने वाले ब्लॉग पोस्ट में उस पर और अधिक पढ़ें ।

पिछले संस्करणों के लिए

डेटा के केवल स्लाइस को पुनः प्राप्त करने के लिए, स्प्रिंग डेटा पृष्ठांकन अमूर्त का उपयोग करता है जो Pageableअनुरोध पक्ष पर एक इंटरफ़ेस के साथ-साथ Pageचीजों के परिणाम पक्ष पर एक अमूर्तता के साथ आता है । तो आप के साथ शुरू कर सकता है

public interface UserRepository extends Repository<User, Long> {

  List<User> findByUsername(String username, Pageable pageable);
}

और इसे इस तरह उपयोग करें:

Pageable topTen = new PageRequest(0, 10);
List<User> result = repository.findByUsername("Matthews", topTen);

यदि आपको परिणाम के संदर्भ को जानने की जरूरत है (कौन सा पृष्ठ वास्तव में है? क्या यह पहला है? कुल कितने हैं?), Pageरिटर्न प्रकार के रूप में उपयोग करें:

public interface UserRepository extends Repository<User, Long> {

  Page<User> findByUsername(String username, Pageable pageable);
}

ग्राहक कोड तो कुछ इस तरह से कर सकते हैं:

Pageable topTen = new PageRequest(0, 10);
Page<User> result = repository.findByUsername("Matthews", topTen);
Assert.assertThat(result.isFirstPage(), is(true));

ऐसा नहीं है कि हम Pageरिटर्न प्रकार के रूप में उपयोग किए जाने वाले वास्तविक क्वेरी की एक गणना प्रक्षेपण को ट्रिगर करेंगे क्योंकि हमें यह पता लगाने की आवश्यकता है कि मेटाडेटा की गणना करने के लिए कुल कितने तत्व हैं। इससे परे, सुनिश्चित करें कि आप वास्तव में PageRequestस्थिर परिणाम प्राप्त करने के लिए छंटाई जानकारी से लैस हैं । अन्यथा आप क्वेरी को दो बार ट्रिगर कर सकते हैं और अलग-अलग परिणाम प्राप्त कर सकते हैं यहां तक ​​कि बिना डेटा बदले भी।


14
धन्यवाद, लेकिन मैं अभी भी 'एनोटेशन आधारित' समाधान के लिए आशा करता हूं। क्योंकि इस मामले में 'पेज / पेजेबिल' बहुत अधिक हैं। और क्लाइंट को 'एक और केवल एक' परिणाम प्राप्त करने के लिए एक पेजेबल / पेज बनाना होगा ... यह उपयोग करने के लिए बहुत ही अनुकूल है। और ऐसा लगता है कि आप स्प्रिंग-डेटा के प्रभारी हैं, मुझे आशा है कि आप इस समस्या पर ध्यान दे सकते हैं: stackoverflow.com/questions/9276461/… । क्या आप पुष्टि कर सकते हैं कि यह स्प्रिंग-डेटा बग है?
smallufo

1
+ यह काम करता है, धन्यवाद लेकिन एक एनोटेशन आधारित समाधान नए संस्करणों में बेहतर होगा
अजराफती

1
एक गणना क्वेरी को यहां निकाल दिया जाता है जो कि यदि हम एक सीमित क्वेरी चाहते हैं तो पूरी तरह अनावश्यक है।
अजराफती

1
यदि आप Listविधि के रिटर्न प्रकार के रूप में उपयोग करते हैं तो यह नहीं है ।
ओलिवर ड्रोट्बोहम

3
मुझे लगता है, Topऔर Firstकीवर्ड @Queryएनोटेशन का उपयोग करने वाले तरीकों पर लागू नहीं होते हैं ? केवल वे, जो विधि-नाम-आधारित क्वेरी पीढ़ी का उपयोग करते हैं?
रुस्लान स्टेलमाचेंको

106

यदि आप जावा 8 और स्प्रिंग डेटा 1.7.0 का उपयोग कर रहे हैं, तो आप @Queryअधिकतम तरीकों की स्थापना के साथ एनोटेशन को संयोजित करना चाहते हैं, तो आप डिफ़ॉल्ट तरीकों का उपयोग कर सकते हैं :

public interface UserRepository extends PagingAndSortingRepository<User,Long> {
  @Query("from User u where ...")
  List<User> findAllUsersWhereFoo(@Param("foo") Foo foo, Pageable pageable);

  default List<User> findTop10UsersWhereFoo(Foo foo) {
    return findAllUsersWhereFoo(foo, new PageRequest(0,10));
  }

}

3
एकल परिणाम के लिए संभावित रूप से उपयोगी हैStream<User> ... {...} default Optional<User> ... { ...findAny() }
xenoterracide

28

एक तरीका है जो आप "a setMaxResults (n) को एनोटेशन द्वारा" के समान प्रदान कर सकते हैं जैसे कि निम्नलिखित में:

public interface ISomething extends JpaRepository<XYZ, Long>
{
    @Query("FROM XYZ a WHERE a.eventDateTime < :before ORDER BY a.eventDateTime DESC")
    List<XYZ> findXYZRecords(@Param("before") Date before, Pageable pageable);
}

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

new PageRequest(0, 10)

यदि आप Pagable का उपयोग कर रहे हैं, तो उसका रिटर्न पेज <XYZ> नहीं सूची <XYZ>
अरुणदेव

@Arundev गलत - Listपूरी तरह से काम करता है (और countपहले से बताई गई टिप्पणी के अनुसार एक अनावश्यक क्वेरी से बचता है )
Janaka Bandara

21

स्प्रिंग डेटा इवांस (1.7.0 RELEASE) का उपयोग करें

स्प्रिंग डेटा JPA की नई रिलीज़ में इवांस नामक मॉड्यूल की एक और सूची के साथ कीवर्ड का उपयोग करने Top20और Firstक्वेरी परिणाम को सीमित करने की सुविधा है।

तो अब आप लिख सकते हैं

List<User> findTop20ByLastname(String lastname, Sort sort);

या

List<User> findTop20ByLastnameOrderByIdDesc(String lastname);

या एक परिणाम के लिए

List<User> findFirstByLastnameOrderByIdDesc(String lastname);

5
वैकल्पिक <उपयोगकर्ता> findFirstByLastnameOrderByIdDesc (अंतिम नाम स्ट्रिंग);
krmanish007

शीर्ष 20 परिणाम प्राप्त करने के बाद, मैं अगले 20 परिणाम कैसे प्राप्त करूंगा जब मैं पेजेशन का उपयोग करके वेबसाइट पर अगले पृष्ठ पर जाऊंगा?
किट्टू

@ किट्टू, निश्चित रूप से एक और सवाल है, लेकिन आपको एक Pageableवस्तु पारित करने की आवश्यकता है । वसंत प्रलेखन की जाँच करें
azerafati

अगर उन्होंने FIRST को निर्दिष्ट किया है तो उन्होंने विधि को एक लानत सूची में कैसे लौटाया ??
वासिल सुड्डू

13

मेरे लिए सबसे अच्छा विकल्प देशी क्वेरी है:

@Query(value="SELECT * FROM users WHERE other_obj = ?1 LIMIT 1", nativeQuery = true)
User findByOhterObj(OtherObj otherObj);

निश्चित नहीं है कि यदि सीमा हाइबरनेट में समर्थित है: forum.hibernate.org/viewtopic.php?f=9&t=939314
विटोल काकज़ुरबा

2
पूरी अवधारणा को तोड़ता है! इसके बजाय बेहतर EntityManager का उपयोग करें!
१२:३० पर स्पेकटाकुलैटिस

@ Code.IT मैं प्रचार KISS अवधारणा। इसके अलावा जेपीए nativeQuery एनोटेशन पैरामीटर ने अनदेखी के लिए नहीं जोड़ा।
ग्रिगोरी किसलिन

@GKislin से आपको फिर से नाम बदलना होगा जैसे findLimitOneByOtherObj। इसके अलावा आप एक ऑर्डरबी को जोड़ना भूल गए हैं जो गलत परिणाम की ओर ले जाता है अगर अन्य_बज अद्वितीय नहीं है। अन्यथा एक अनूठे स्तंभ पर एक बयान एक सीमा के बिना पर्याप्त होना चाहिए
Spektakulatius

आप LIMIT कीवर्ड हाइबरनेट नहीं है, लेकिन postgres / mysql
AceWin

5

यदि आपकी कक्षा @Repositoryफैली हुई है, JpaRepositoryतो आप नीचे दिए गए उदाहरण का उपयोग कर सकते हैं।

int limited = 100;
Pageable pageable = new PageRequest(0,limited);
Page<Transaction> transactionsPage = transactionRepository.findAll(specification, pageable);
return transactionsPage.getContent();

getContent वापसी a List<Transaction>


क्या होगा यदि मेरे पास क्वेरी में 2 स्थितियां हैं जैसे, transactionRepository.findByFirstNameAndLastName (firstname, lastname)? क्या ये काम करेगा ? मुझे यह अपवाद मिल रहा है। org.springframework.data.mapping.PropertyReferenceException: कोई संपत्ति प्रकार बोर्ड के लिए नहीं बनाई गई है।
शैलेश

4

यह @QueryHints का उपयोग करके भी पॉसिबल है। उदाहरण bellow में org.eclipse.persistence.config.QueryHints # JDBC_MAX_ROWS का उपयोग किया जाता है

@Query("SELECT u FROM User u WHERE .....")
@QueryHints(@QueryHint(name = JDBC_MAX_ROWS, value = "1"))
Voter findUser();

मैंने इस कोड का परीक्षण किया है लेकिन यह काम नहीं कर रहा है। कोई अपवाद नहीं है, लेकिन कोई उचित परिणाम नहीं है। इसके अलावा प्रलेखन QueryHints के बारे में बहुत पतली है। निचे देखो। docs.spring.io/spring-data/jpa/docs/1.7.1.RELEASE/reference/…
bogdan.rusu

IIRC, कोई गारंटी नहीं है कि एक क्वेरी संकेत का पालन किया जाएगा। यह कार्यान्वयन के लिए "दोस्ताना सिफारिशें" पारित करने का एक तरीका है।
प्रिवु नीमरे

मैं @QueryHints({@QueryHint(name = org.hibernate.annotations.FETCH_SIZE, value = "1")})हाइबरनेट में इसके साथ कोशिश करता हूं , लेकिन उपनाम :( काम नहीं करता है
ग्रिंजरी किसलिन

2
org.hibernate.annotations.FETCH_SIZE इसका फ़ोकस आकार, इसकी सीमा नहीं, अधिकतम परिणाम नहीं हाइबर कैंट
विटालि

4

new PageRequest(0,10)नए स्प्रिंग संस्करणों में काम नहीं करता (मैं उपयोग कर रहा हूं 2.2.1.RELEASE)। मूल रूप से, निर्माता को एक अतिरिक्त पैरामीटर मिला है Sort। इसके अलावा, कंस्ट्रक्टर protectedऐसा है कि आपको उसके किसी एक बच्चे की कक्षा का उपयोग करना है या उसकी ofस्थैतिक विधि को कॉल करना है :

PageRequest.of(0, 10, Sort.sort(User.class).by(User::getFirstName).ascending()))

आप Sortपैरामीटर के उपयोग को भी छोड़ सकते हैं और अंतर्निहित उपयोगकर्ता को डिफ़ॉल्ट सॉर्ट (पीके, आदि के आधार पर छाँटें) कर सकते हैं:

PageRequest.of(0, 10)

आपकी फ़ंक्शन घोषणा कुछ इस तरह होनी चाहिए:

List<User> findByUsername(String username, Pageable pageable)

और समारोह होगा:

userRepository.findByUsername("Abbas", PageRequest.of(0,10, Sort.sort(User.class).by(User::getLastName).ascending());
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.