2012-04-18 8 views
13

मुझे पता है कि इससे पहले पूछा गया है, लेकिन मैं अब तक मिली जानकारी के आधार पर समाधान लागू करने में सक्षम नहीं था। तो शायद कोई मुझे यह समझा सकता है।MyBatis enum उपयोग

मेरे पास एक टेबल "स्थिति" है। इसमें दो कॉलम हैं: आईडी और नाम। आईडी एक पीके है।

POJO स्थिति का उपयोग करने के बजाय, मैं एक enum का उपयोग करना चाहता हूं।

public enum Status { 
    NEW(1), READY(2), CLOSED(3); 

    private int id; 

    public void setId(int id) { 
     this.id = id; 
    } 

    public int getId() { 
     return this.id; 
    } 

    Status(int id) { 
     this.id = id; 
    } 
} 

यहाँ मेरी नक्शाकार

 <select id="getStatusByName" resultType="Status" parameterType="String">  
     SELECT ls.id, ls.name 
     FROM status AS ls 
     WHERE ls.name = #{name} 
    </select> 

लेकिन किसी कारण के लिए है, जब मैं एक enum, कुछ टूट जाता है प्राप्त करने का प्रयास है, लेकिन कोई अपवाद: मैं इस तरह के एक enum इस प्रकार बनाया फेंक दिया गया है

+1

ISTM जो एक enum पर सेट() सेट एक भयानक विचार है ... :) –

उत्तर

18

मैंने इस प्रश्न पर कुछ कोणों से काम किया है और यहां मेरे निष्कर्ष हैं। चेतावनी: मैंने MyBatis-3.1.1 का उपयोग करके इन सभी जांचें कीं, इसलिए पिछले संस्करणों में चीजें अलग-अलग व्यवहार कर सकती थीं।

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

एक उदाहरण बेहतर चित्रित करेगा। मान लीजिए कि उपर्युक्त आपकी क्वेरी 2 और "Ready" लौटाती है जब मैं तर्क के रूप में "तैयार" में जाता हूं। उस स्थिति में, मुझे त्रुटि संदेश No enum constant com.foo.Status.2 मिलता है। अगर मैं

SELECT ls.name, ls.id 

होने के लिए अपने SELECT कथन का क्रम उलटने तो त्रुटि संदेश No enum constant com.foo.Status.Ready है। मुझे लगता है कि आप अनुमान लगा सकते हैं कि MyBatis क्या कर रहा है। ध्यान दें कि EnumTypeHandler क्वेरी से लौटाए गए दूसरे मान को अनदेखा कर रहा है।

SELECT UPPER(ls.name) 

को आपकी क्वेरी को बदलने का कारण बनता है यह काम करने के लिए: Status.READY enum दिया जाता है।

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

तब मैंने सोचा कि मुझे चालाक मिल जाएगा और एक माईबेटिस ऑब्जेक्ट फैक्ट्री लागू होगा, इंट आईडी और स्ट्रिंग नाम दोनों को पकड़ लें और सुनिश्चित करें कि वे जावा एनम में मेल खाते हैं, लेकिन यह काम नहीं करता क्योंकि मायबेटिस कॉल नहीं करता जावा एनम प्रकार के लिए ऑब्जेक्ट फैक्ट्री (कम से कम मैं इसे काम नहीं कर सका)।

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

अंत में, यदि आप इसका एक कामकाजी उदाहरण देखना चाहते हैं, तो यहां मेरे MyBatis कोनों के कोन 23 देखें: https://github.com/midpeter444/mybatis-koans। यदि आप बस मेरा समाधान देखना चाहते हैं, तो पूर्ण-कोन्स/koan23 निर्देशिका देखें। मेरे पास जावा एनम के माध्यम से डेटाबेस में रिकॉर्ड डालने का एक उदाहरण भी है।

6

आप सीधे परिणाम ENUM में परिवर्तित करने के लिए कस्टम टाइप हैंडलर का उपयोग कर सकते हैं ताकि आपको अपर केस के नाम के रूप में अपने डेटाबेस में सभी मानों को रखने की आवश्यकता न हो।

यह आपके स्थिति Enum कस्टम हैंडलर की तरह

public class StatusTypeHandler implements TypeHandler<Status> { 

public Status getResult(ResultSet rs, String param) throws SQLException { 
    return Status.getEnum(rs.getInt(param)); 
} 

public Status getResult(CallableStatement cs, int col) throws SQLException { 
    return Status.getEnum(cs.getInt(col)); 
} 

public void setParameter(PreparedStatement ps, int paramInt, Status paramType, JdbcType jdbctype) 
     throws SQLException { 
    ps.setInt(paramInt, paramType.getId()); 
} 
} 

कैसे दिखेगा इस कोड को जोड़कर अपने mybatis-config.xml में डिफ़ॉल्ट रूप से स्थिति को संभालने के लिए अपने TypeHandler परिभाषित है।

<typeHandlers> 
      <typeHandler javaType='Status' handler='StatusTypeHandler' /> 
    </typeHandlers> 

अब

Status getStatusById(int code); 
Status getStatusByName(String name); 

आपका नक्शाकार तरह

<select id="getStatusById" resultType="Status" parameterType="int">  
    SELECT ls.id 
    FROM status AS ls 
    WHERE ls.id = #{id} 
</select> 

<select id="getStatusByName" resultType="Status" parameterType="String">  
    SELECT ls.id 
    FROM status AS ls 
    WHERE ls.name = #{name} 
</select> 

अब दिखेगा दोनों नक्शाकार के लिए resultType के रूप में, हमें एक उदाहरण है जहाँ आप अपने दाव में दो कार्य निम्नलिखित है पर विचार करते हैं स्थिति है, myBatis इस प्रकार के लिए कस्टम टाइप टाइपलर का उपयोग करेगा यानी एनमटाइप हैंडलर के बजाय स्टेटस टाइपपैंडर जो कि डिफ़ॉल्ट रूप से हैंडलिंग एनम्स के लिए उपयोग करता है, इसलिए उचित एनम को बनाए रखने की कोई आवश्यकता नहीं होगी आपके डेटाबेस में नाम।

+0

क्या होगा यदि मुझे तर्क (आईडी, नाम, आदि) गुजरने के बिना enum वापस करने की आवश्यकता है? – axcdnt

+2

वह उत्तर है जो एक स्वच्छ समाधान प्रदान करता है। अपरकेस पर निर्भर बदसूरत है। – Eduardo