2009-05-12 14 views
19

से मूल्यों के साथ एक enum पॉप्युलेट करें मेरे पास एक सारणी है जो स्ट्रिंग-> इंटीजर नक्शा रखती है।डेटाबेस

एक enum स्थिर रूप से बनाने के बजाय, मैं डेटाबेस से मूल्यों के साथ enum populate करना चाहता हूँ। क्या यह संभव है ?

तो, बजाय यह स्थिर delcaring:

public enum Size { SMALL(0), MEDIUM(1), LARGE(2), SUPERSIZE(3) }; 

मैं गतिशील इस enum बनाना चाहते हैं के बाद से संख्या {0,1,2,3} मूल रूप से यादृच्छिक हैं (क्योंकि वे डेटाबेस के AutoIncrement द्वारा स्वतः जेनरेट कर रहे हैं स्तंभ)।

+0

डुप्लिकेट: http://stackoverflow.com/questions/725043/dynamic-enum-in-c – aleemb

+4

कि सिवाय सी #, जावा के लिए था, और हम सभी जानते हैं आप जावा के साथ कुछ कर सकते हैं :-) – paxdiablo

उत्तर

25

सं। समय पर संकलन हमेशा तय किए जाते हैं। एकमात्र तरीका यह है कि आप इसे निष्क्रिय बाइटकोड उत्पन्न करना होगा।

यह कहकर, आपको संभवतया यह पता लगाना चाहिए कि आप वास्तव में रुचि रखने वाले enum के कौन से पहलू हैं। संभवतः आप उन पर switch कथन का उपयोग नहीं करना चाहते थे, क्योंकि इसका मतलब स्थिर कोड होगा और आप नहीं मूल्यों को स्थिर रूप से जानें ... इसी प्रकार कोड में कोई अन्य संदर्भ।

यदि आप वास्तव में String से Integer पर मानचित्र चाहते हैं, तो आप केवल Map<String, Integer> का उपयोग कर सकते हैं जिसे आप निष्पादन समय पर पॉप्युलेट करते हैं, और आप कर चुके हैं। यदि आप EnumSet फीचर्स चाहते हैं, तो वे एक ही दक्षता के साथ पुन: पेश करने के लिए कुछ हद तक कठिन होंगे, लेकिन कुछ प्रयासों के साथ यह संभव हो सकता है।

तो, कार्यान्वयन के बारे में सोचने के मामले में आगे जाने से पहले, मेरा सुझाव है कि आप काम करें कि आपकी वास्तविक आवश्यकताएं क्या हैं।

(संपादित करें: मुझे लगता है कि यह enum पूरी तरह गतिशील है, यानी कि आप नामों को नहीं जानते हैं या यहां तक ​​कि कितने मूल्य हैं। यदि नामों का सेट तय किया गया है और आप केवल की आवश्यकता है डेटाबेस से आईडी प्राप्त करें, यह एक बहुत ही अलग मामला है - Andreas' answer देखें।)

+1

बीनशेल को देखो यदि आप गतिशील रूप से कोड उत्पन्न करना चाहते हैं और इसे रनटाइम पर संकलित करना चाहते हैं। –

2

Enums गतिशील नहीं हैं, इसलिए संक्षिप्त जवाब यह है कि आप इसे नहीं कर सकते हैं।

स्टैक ओवरफ़्लो प्रश्न Dynamic enum in C# पर भी एक नज़र डालें।

0

सभी भाषाओं में मुझे पता है कि enums स्थिर हैं। संकलक उन पर कुछ अनुकूलन कर सकते हैं। इसलिए संक्षिप्त जवाब नहीं है, आप नहीं कर सकते हैं।

सवाल यह है कि आप इस तरह से एक enum का उपयोग क्यों करना चाहते हैं। आप क्या उम्मीद करते हैं? या दूसरे शब्दों में क्यों इसके बजाय संग्रह का उपयोग नहीं करते?

+0

विरासत कोड, जहां एक ऐसी जगह है जो पूरे स्थान पर उपयोग की जाती है जिसे अब हम डेटाबेस से गतिशील रूप से लोड करना चाहते हैं। अगर आप फ्लाई पर एनम लोड कर सकते हैं तो उचित मात्रा में रिफैक्टरिंग बचाता है ... –

21

यह थोड़ा मुश्किल है, क्योंकि उन मूल्यों की आबादी कक्षा-लोड समय पर होती है। तो आपको डेटाबेस कनेक्शन में स्थिर पहुंच की आवश्यकता होगी।

जितना मैं अपने उत्तरों की कीमत मानता हूं, मुझे लगता है कि इस समय जॉन स्कीट गलत हो सकता है।

इस पर एक नज़र डालें:

public enum DbEnum { 
    FIRST(getFromDb("FIRST")), SECOND(getFromDb("second")); 

    private static int getFromDb(String s) { 
     PreparedStatement statement = null; 
     ResultSet rs = null; 
     try { 
      Connection c = ConnectionFactory.getInstance().getConnection(); 
      statement = c.prepareStatement("select id from Test where name=?"); 
      statement.setString(1, s); 
      rs = statement.executeQuery(); 
      return rs.getInt(1); 

     } 
     catch (SQLException e) { 
      throw new RuntimeException("error loading enum value for "+s,e); 
     } 
     finally { 
      try { 
       rs.close(); 
       statement.close(); 
      } catch (SQLException e) { 
       //ignore 
      } 
     } 
     throw new IllegalStateException("have no database"); 
    } 

    final int value; 

    DbEnum(int value) { 
     this.value = value; 
    } 
} 
+3

आप मानते हैं कि आप * संकलन-समय * कितने मूल्य होंगे, और उन्हें क्या कहा जाना चाहिए। यदि ऐसा है, तो यह ठीक है - लेकिन मुझे इस प्रश्न में कुछ भी दिखाई नहीं देता है जो बताता है। (मुझे लगता है कि आपकी क्वेरी आईडी के साथ भी चयन करनी चाहिए, सिर्फ 1 :) –

+2

एक सूचनात्मक प्रतिक्रिया जो हमें enums के ऑब्जेक्ट उन्मुख पहलुओं के बारे में याद दिलाती है - धन्यवाद, एंड्रियास। –

+0

(देर से जवाब, मुझे पता है) आप सोचते हैं कि मूल्यों को पॉप्युलेट करने के लिए प्रतिबिंब का उपयोग करके आप इस ड्रियर को बना सकते हैं। तो क्या आपके पास पहले() हो सकता है और प्रारंभिक कोड में नाम दिख सकता है? – Rich

1

आप कोड में दोहराने के लिए क्या डेटाबेस (या इसके विपरीत) में है की जरूरत है। कुछ अच्छी सलाह के लिए यह question देखें।

5

what Andreas did पर सुधार, आप डेटाबेस कनेक्शन की संख्या को कम करने के लिए डेटाबेस में सामग्री को लोड कर सकते हैं।

public enum DbEnum { 
    FIRST(getFromDb("FIRST")), 
    SECOND(getFromDb("second")); 

    private Map<String,Integer> map; 
    private static int getFromDB(String s) 
    { 
     if (map == null) 
     { 
      map = new HashMap<String,Integer>(); 
      // Continue with database code but get everything and 
      // then populate the map with key-value pairs. 
      return map.get(s); 
     } 
     else { 
      return map.get(s); } 
    } 
} 
+0

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