JdbcTemplate queryForInt / Long को स्प्रिंग 3.2.2 में चित्रित किया गया है। इसे किसके द्वारा प्रतिस्थापित किया जाना चाहिए?


104

JdbcTemplate में queryforInt / queryforLong तरीके स्प्रिंग 3.2 में चित्रित किए गए हैं। मैं पता नहीं लगा सकता कि इन तरीकों का उपयोग करके मौजूदा कोड को बदलने के लिए सबसे अच्छा अभ्यास क्यों या क्या माना जाता है।

एक विशिष्ट विधि:

int rowCount = jscoreJdbcTemplate.queryForInt(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    playerNameKey.toUpperCase(),
    teamNameKey.toUpperCase()
);

उपर्युक्त विधि को निम्न प्रकार से फिर से लिखना होगा:

Object[] params = new Object[] { 
   playerNameKey.toUpperCase(), 
   teamNameKey.toUpperCase()
};
int rowCount = jscoreJdbcTemplate.queryForObject(
    "SELECT count(*) FROM _player WHERE nameKey = ? AND teamClub = ?",
    params, Integer.class);

स्पष्ट रूप से यह अपवर्जन JdbcTemplate वर्ग को सरल बनाता है (या करता है?)। QueryForInt हमेशा एक सुविधा विधि थी (मुझे लगता है) और एक लंबे समय के आसपास रही है। क्यों हटाया गया है। परिणामस्वरूप कोड अधिक जटिल हो जाता है।


इस विवरण ने विधियों को चित्रित किया
Dan MacBean

आप ठीक कह रहे हैं, मुझे नहीं पता कि मेरे स्रोत में क्यों नहीं है@Deprecated
सोतीरियोस डेलिमोलिस 14

स्प्रिंग संस्करण को 3.2.2 पर अपडेट किया गया - जैसा कि लगता है कि यह पहली बार यहाँ
चित्रित किया

मैंने मौजूदा कोडबेस को 3.1 से 3.2.2 तक अपग्रेड किया है और इन तरीकों का इस्तेमाल सभी जगह किया जाता है। कोड को क्यों और कैसे अपडेट करना है, यह समझने की आवश्यकता है।
डैन मैकबैन

ध्यान रखें कि queryForObject वापस आ सकता है null(आपके उदाहरण में मामला नहीं)। मुझे अब डुप्लिकेट चेक कोड से कोई दूसरा रास्ता नहीं मिला, जो कि क्वेरीफ़र्ट / लॉन्ग से शून्य चेक कोड है।
होचराल्डो

जवाबों:


110

मुझे लगता है कि किसी ने महसूस किया है कि queryForInt / लॉन्ग मेथड्स में भ्रामक शब्दार्थ है, यानी JdbcTemplate स्रोत कोड से आप इसका वर्तमान कार्यान्वयन देख सकते हैं:

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    Number number = queryForObject(sql, args, Integer.class);
    return (number != null ? number.intValue() : 0);
}

जो आपको यह सोचने के लिए प्रेरित कर सकता है कि यदि परिणाम सेट खाली है तो यह 0 पर वापस आ जाएगा, हालांकि यह एक अपवाद फेंकता है:

org.springframework.dao.EmptyResultDataAccessException: Incorrect result size: expected 1, actual 0

इसलिए निम्नलिखित कार्यान्वयन अनिवार्य रूप से वर्तमान के बराबर है:

@Deprecated
public int queryForInt(String sql, Object... args) throws DataAccessException {
    return queryForObject(sql, args, Integer.class);
}

और फिर गैर पदावनत कोड अब बदसूरत के साथ प्रतिस्थापित किया जाना चाहिए:

    queryForObject(sql, new Object { arg1, arg2, ...}, Integer.class);

या यह (अच्छे):

    queryForObject(sql, Integer.class, arg1, arg2, ...);

12
यह सच नहीं है। तीसरा कोड स्निपेट कार्यान्वयन के बराबर नहीं है! क्योंकि ऑटो अनबॉक्सिंग के साथ एक छिपा हुआ एनपीई है। यदि आपकी क्वेरी परिणाम लौटाती है, लेकिन वे शून्य थे, तो पिछला कोड शून्य के बजाय 0 वापस आ जाएगा - पिछले व्यवहार को ठीक से पुन: पेश करने के लिए, यह होगा: Integer result = queryForObject (sql, args, Integer.class); वापसी परिणाम == अशक्त? 0: परिणाम;
MetroidFan2002

@ MetroidFan2002: वास्तव में आपका अवलोकन सत्य है! हालाँकि, API डिज़ाइन के दृष्टिकोण से, यदि क्वेरी सिर्फ एक NULL मान लौटाती है, मेरा मानना ​​है कि इसे वापस करना बेहतर है, यह मानने के बजाय कि (queryForInt करते हैं) NULL 0. के बराबर है। यह काम है इस तरह की स्थितियों का मूल्यांकन करने के लिए एपीआई उपयोगकर्ता।
गैब्रियल भाषाविदों

समस्या यह है कि अगर और जब कोई उपयोगकर्ता वहां एनपीई प्राप्त करता है, जब तक कि वे स्पष्ट रूप से अपने वातावरण में कुछ चीजें निर्धारित नहीं करते हैं (उदाहरण के लिए, ग्रहण में ऑटोबॉक्सिंग के उपयोग को उजागर करने का एक विकल्प है), तो उस लाइन पर एनपीई JDBCOperations उदाहरण की तरह दिखेगा शून्य है। पहले, शून्य वापस कर दिया गया होगा। अब आप इसे एक ऐसी क्वेरी में क्यों उपयोग करेंगे जो अशक्त है, मुझे पता नहीं है (यह मूल रूप से ऐसा करने वाले n00bs के कारण है, जो वे करेंगे), लेकिन इन को दूर करना एक महान कदम आईएमओ नहीं है।
MetroidFan2002

मैंने पाया कि अशुद्धि के कारण एक संभावित कारण है। मेरे पास क्वेरीफोरलॉन्ग (स्ट्रिंग) द्वारा लौटाए जा रहे 10000000233174211 का एक लंबा मूल्य था, लेकिन इसके बजाय यह 10000000233174212 लौट रहा था। अर्थात +1। मैंने कोड में देखा और यह एक डबल को एक लंबे समय में परिवर्तित करता है, इसलिए शायद रूपांतरण के साथ कुछ समस्या है।
mrswadge

थोड़ा और ऊपर मेरी टिप्पणी के बारे में सोचकर, कॉलम के लिए डेटा प्रकार संख्या (19,0) था, इसलिए शायद यही कारण है कि डबल खेलने में आया? मैं किसी भी तरह queryForObject (sql, Long.class) का उपयोग करके समस्या के आसपास गया।
21

35

मैं मूल पोस्टर से सहमत हूं कि सुविधा विधि क्वेरीफ्रॉन्गॉन्ग (एसक्यूएल) को हटाना एक असुविधा है।

मैंने स्प्रिंग 3.1 का उपयोग करके एक ऐप विकसित किया था और बस नवीनतम स्प्रिंग संस्करण (3.2.3) में अपडेट किया और ध्यान दिया कि इसे हटा दिया गया था।

सौभाग्य से, यह मेरे लिए एक परिवर्तन था:

return jdbcTemplate.queryForLong(sql);  // deprecated in Spring 3.2.x

को बदल दिया गया था

return jdbcTemplate.queryForObject(sql, Long.class);

और यूनिट टेस्ट के एक जोड़े को इंगित करने के लिए लगता है, उपरोक्त परिवर्तन काम करता है।


अच्छी बात। यह कोष्ठक के बिना भी ठीक काम करेगा। :)
SGB


13

ऐसे कोड को बदलना:

long num = jdbcTemplate.queryForLong(sql);

इस कोड के साथ:

long num = jdbcTemplate.queryForObject(sql, Long.class);

बहुत खतरनाक है क्योंकि यदि स्तंभ में शून्य मान क्वेरी है तो OOOOject वापसी नल और जैसा कि हम जानते हैं कि आदिम प्रकार शून्य नहीं हो सकते हैं और आपके पास NullPointerException होगी। संकलक ने आपको इस बारे में चेतावनी नहीं दी। इस त्रुटि के बारे में आपको रनटाइम में पता चल जाएगा। एक ही त्रुटि यदि आपके पास आदिम प्रकार वापस करने की विधि है:

public long getValue(String sql) {
    return = jdbcTemplate.queryForObject(sql, Long.class);
}

स्प्रिंग 3.2.2 में JdbcTemplate में पदावनत विधि क्वेरीफोरलॉन्ग में निम्नलिखित निकाय हैं:

@Deprecated
public long queryForLong(String sql) throws DataAccessException {
    Number number = queryForObject(sql, Long.class);
    return (number != null ? number.longValue() : 0);
}

आप देखते हैं कि इससे पहले कि वे आदिम मान लौटाते हैं, यह जाँच लें कि यह शून्य नहीं है और यदि यह शून्य है तो वे 0. लौटें। वैसे - 0 एल होना चाहिए।


3
2 सेंट: कंपाइलर आपको इसके बारे में चेतावनी दे सकता है, यदि आपने ऑटोबॉक्सिंग चेतावनी सक्षम की है।
कीकी

मुझे इसके बारे में पता नहीं था। धन्यवाद दोस्त :)
Marcin Kapusta

2

JdbcTemplate#queryForIntयदि स्तंभ मान SQL NULL या 0. है तो 0 देता है। एक मामले को दूसरे से अलग करने का कोई तरीका नहीं है। मुझे लगता है कि यह मुख्य कारण है कि विधि को पदावनत क्यों किया जाता है। BTW, ResultSet#getIntइसी तरह व्यवहार करता है। हालाँकि, हम इन दो मामलों के बीच अंतर कर सकते हैं ResultSet#wasNull


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