2012-02-07 15 views
8

मेरे पास वर्तमान में निम्न कोड है जो डेटाबेस से डेटा पुनर्प्राप्त करता है और फिर User बनाता है। News, Comments आदि जैसे अन्य ऑब्जेक्ट्स बनाने के लिए इस कोड का उपयोग मेरे कई क्लैस में किया जाता है ...जावा जेनेरिक कन्स्ट्रक्टर

यह अपाचे कॉमन्स dbutils का उपयोग करता है।

final ResultSetHandler<User> handler = new ResultSetHandler<User>() { 

      @Override 
      public User handle(ResultSet rs) throws SQLException { 

       User user = null; 
       if (rs.next()) { 
        user = new User(); 
        user.setId(rs.getInt("id")); 
        user.setUsername(rs.getString("username")); 
        user.setPassword(rs.getString("password")); 
       } 
       return user; 
      } 
     }; 

     final User user = run.query(
       "SELECT id, username, password FROM users WHERE username = ? AND active = 2 LIMIT 1;", handler, 
       username); 

यह एक सामान्य वर्ग में QueryRunner लपेट और इतने सामान्य T ResultSet साथ instanciate हैंडलर क्वेरी विधि ओवरराइड करने के लिए संभव है। मैं सुनिश्चित करता हूं कि T प्रकार ResultSet को स्वीकार करने वाला एक निर्माता होगा।

तो जैसा

:

 public class QueryExecuter<T> extends QueryRunner { 
    private ResultSetHandler<T> _handler; 

    public QueryExecuter(){//The T type was for testing haha 
     super(); 
     handler = new ResultSetHandler<T>() { 

      @Override 
      public T handle(ResultSet rs) throws SQLException { 

       T object = null; 
       if (rs.next()) { 
        object = new T(rs); 
       } 
       return object; 
      } 
     }; 
    } 
} 

मैं अगर आप समझ जाएंगे कि पता नहीं है, लेकिन मैं तो उम्मीद है, मुझसे पूछते हैं अगर आप अधिक विवरण या एक बेहतर स्पष्टीकरण चाहते हैं।

संपादित

मैं मैं सामान्य प्रकार है कि विभिन्न वस्तुओं के सभी होगा फैली के बजाय एक AbstractClass इस्तेमाल कर सकते हैं सोचा लेकिन ऐसा लगता है जैसे मैं एक सार निर्माता नहीं लिख सकते हैं। क्या मुझे एक स्थिर विधि बनाना होगा जो ऑब्जेक्ट का उदाहरण लौटाए:

public abstract class DatabaseEntity { 
    public static abstract DatabaseEntity create(ResultSet rs);//even this doesn't work... 
} 
+0

आपको कन्स्ट्रक्टर में 'टी टाइप' पास करने की आवश्यकता क्यों है? – yair

+0

प्रतिबिंब का उपयोग करें आप परिणाम सेट –

उत्तर

8

संभव, हाँ? लेकिन यह एक बुरा विचार है।

आप कर सकता है:

class ResultSetHandler<T> { 
    ResultSetHandler<T>(Class<T> clazz) { 
    this.clazz = clazz; 
    } 

    public T handle(ResultSet rs) throws SQLException { 
    T object = null; 
    if (rs.next()) { 
     object = clazz.getConstructor(ResultSet.class).newInstance(rs) 
    } 
    return object; 
    } 
} 

डोमेन और डेटाबेस मिश्रण लेकिन एक बुरा विचार है। बेहतर होगा क्या, तथापि, एक abtract विधि है कि resultset के आधार पर वस्तु बनाता है परिभाषित करने के लिए किया जाएगा:

abstract class ResultSetHandler<T> { 

    protected abstract T create(ResultSet rs); 

    public T handle(ResultSet rs) throws SQLException { 
    T object = null; 
    if (rs.next()) { 
     object = create(rs); 
    } 
    return object; 
    } 
} 

फिर, अपने को लागू कक्षा में, आप केवल परिणाम से निपटने के बजाय एक create() विधि उपलब्ध कराने की आवश्यकता खुद को सेट करें, उदाहरण के लिए:

h = new ResultSetHandler<Person>() { 
    protected Person create(ResultSet rs) { 
    return new Person(rs.getString("name")); 
    } 
} 
+0

+1 मेरे जैसा ही उत्तर प्रदान करने के लिए +1, लेकिन अच्छे कोड उदाहरण के साथ। –

+0

आप कहते हैं कि डोमेन के साथ डेटाबेस को मिलाकर एक अच्छा विचार नहीं है और मुझे वह मिलता है, लेकिन आप इन ऑब्जेक्ट्स को क्वेरी परिणामों से बनाने के लिए क्या करेंगे? – David

+0

मैं एक एमवीसी आर्किटेक्चर का उपयोग कर रहा हूं, इसलिए मेरा मॉडल दृढ़ता के लिए है और जानता है कि डेटाबेस में खुद को कैसे सहेजना और अपडेट करना है, लेकिन मैं डेटाबेस के विरुद्ध क्वेरी करने के लिए उपयोगिता का उपयोग करता हूं। शायद डीएओ का उपयोग करें? – David

0

मुझे नहीं लगता कि जावा में ऐसा करना संभव है। आप जेनेरिक में T का उदाहरण नहीं बना सकते हैं। जावा में जेनेरिक वास्तव में सी ++ में टेम्पलेट्स नहीं हैं, वे केवल object के आसपास सिंटैक्स चीनी हैं जो कि कास्ट को हटाते हैं और संकलन समय चेतावनियां प्रेरित करते हैं।

T को बाधित करने के लिए सी # में कोई रास्ता नहीं है ताकि इसमें एक कन्स्ट्रक्टर हो।

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

+0

के साथ कक्षा कन्स्ट्रक्टर का आह्वान कर सकते हैं, वह जेबी निजेट ने कहा कि वह प्रतिबिंब के साथ ऐसा कर सकता है। –

+0

निश्चित रूप से संभव है। आपको बस 'कक्षा ' के संदर्भ की आवश्यकता है। प्रतिबिंब के साथ –

+0

हां। आपको अभी भी विधि में वास्तविक वर्ग को पारित करने की आवश्यकता होगी। आप टी.क्लास नहीं जा सकते हैं जैसा आप करना चाहते हैं, कक्षा की जानकारी रनटाइम पर मौजूद थी। – Dervall

3

आप ऐसा कुछ कर सकते हैं (ऑब्जेक्ट के वर्ग को बनाने के लिए, और इसके कन्स्ट्रक्टर को कॉल करने के लिए प्रतिबिंब का उपयोग करके), लेकिन मुझे पीडीजेओ जेडीबीसी पर निर्भर करने के लिए खराब डिजाइन मिलेगा, और न केवल यह जानना यह डेटाबेस में संग्रहीत है, लेकिन यह भी लोड करने के लिए प्रयुक्त क्वेरी में कौन से उपनाम का उपयोग किया गया है।

संक्षेप में, यह बाहरी, अज्ञात क्वेरी के परिणाम सेट को संभालने के लिए उपयोगकर्ता POJO निर्माता की ज़िम्मेदारी नहीं है।

आप एक AbstractSingleEntityHandler सुपर क्लास जो सिर्फ

if (rs.next()) { 

ब्लॉक है, और एक सार विधि करने के लिए वास्तविक इकाई निर्माण प्रतिनिधि हैं डिजाइन सकता है, लेकिन आप ज्यादा लाभ नहीं होगा।

+0

+1 मेरे से तेज़ होने और वास्तव में जो लिखना चाहता था उसे लिखने के लिए;) –

+0

मैं ऐसा करने की कोशिश कर रहा हूं क्योंकि कोड के पहले ब्लॉक में ऊपर दिए गए हैंडलर बॉडी को किसी ऑब्जेक्ट के लिए प्रत्येक क्वेरी में दोहराया जाता है। मैंने सोचा कि यह सुनिश्चित करना अच्छा होगा कि डीबी से आने वाली मेरी वस्तुएं जानती हैं कि क्वेरी परिणाम से खुद को कैसे बनाया जाए, 'query'method सीधे वस्तु को वापस कर देगा। – David

+0

और पीओजेओ द्वारा आपका क्या मतलब है? – David

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