0/1 के बजाय टाइप बूलियन के लिए Y / N को संग्रहीत करने के लिए हाइबरनेट (JPA का उपयोग करके) कॉन्फ़िगर करें


80

क्या मैं Booleanप्रकारों को जारी रखने के लिए JPA / हाइबरनेट सेटअप कर सकता हूं Y/N? डेटाबेस में (कॉलम को इस रूप में परिभाषित किया गया है varchar2(1)। यह वर्तमान में उन्हें स्टोर करता है 0/1। डेटाबेस ओरेकल है।

जवाबों:


8

एकमात्र तरीका मुझे पता चला है कि ऐसा करने के लिए मेरी कक्षा के लिए दो गुण हैं। प्रोग्रामिंग एपीआई के लिए बूलियन के रूप में एक जो मैपिंग में शामिल नहीं है। यह गेटटर और सेटर एक निजी चार चर है जो Y / N है। मेरे पास एक और संरक्षित संपत्ति है जो हाइबरनेट मैपिंग में शामिल है और यह गेटर्स है और सीधे निजी चार चर का संदर्भ देता है।

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


1
मुझे कुछ ऐसा ही करना था - मैंने बुलियन से स्ट्रिंग के सदस्य के प्रकार को बदल दिया। गेटर्स और सेटर्स में (जो मिला और बूलियन सेट किया) मैंने Y / N को संबंधित बूलियन मान में बदलने के लिए कोड लिखा।
219 sengs

@bernardn नहीं, यह बेहतर है।
अलेक्जेंडर

यहाँ एक बेहतर समाधान विचार
on-java.org/hibernate-tips-how-to-map-a-boolean-to-yn

146

हाइबरनेट में एक अंतर्निहित "हां_नो" प्रकार होता है, जो आप चाहते हैं। यह डेटाबेस में एक CHAR (1) कॉलम के लिए मैप करता है।

बुनियादी मानचित्रण: <property name="some_flag" type="yes_no"/>

एनोटेशन मैपिंग (हाइबरनेट एक्सटेंशन):

@Type(type="yes_no")
public boolean getFlag();

28
जो लोग रुचि रखते हैं, उनके लिए एक "true_false" प्रकार भी है जो "T" या "F" को संग्रहीत करेगा।
मैट सोलनिट

यह काम किया, लेकिन मैं इसका उपयोग नहीं कर सका क्योंकि यह एक हाइबरनेट विशिष्ट एनोटेशन है। जवाब के लिए धन्यवाद। एक अलग परियोजना में इसका इस्तेमाल कर सकते हैं।
sengs

यह हाइबरनेट 4 और बाद के लिए है, इसका मतलब है कि जावा 1.6 और बाद के लिए। सीतनिद्रा में होना 3 के लिए काम करते हैं। *
तूफान_बस्टर

7
जब यह जवाब दिया गया तो @storm_buster Hibernate 4 मौजूद नहीं था। यह हाइबरनेट 3.x और जावा 1.5 के साथ पूरी तरह से ठीक काम करता है
ChssPly76

3
फिर 0 या 1 कैसे लगाएं?
JavaTechnical

84

यह गेटर्स / सेटर का उपयोग किए बिना शुद्ध जेपीए है। 2013/2014 तक यह किसी भी हाइबरनेट विशिष्ट एनोटेशन का उपयोग किए बिना सबसे अच्छा जवाब है, लेकिन कृपया ध्यान दें कि यह समाधान जेपीए 2.1 है, और जब यह प्रश्न पहली बार पूछा गया तो उपलब्ध नहीं था:

@Entity
public class Person {    

    @Convert(converter=BooleanToStringConverter.class)
    private Boolean isAlive;    
    ...
}

और तब:

@Converter
public class BooleanToStringConverter implements AttributeConverter<Boolean, String> {

    @Override
    public String convertToDatabaseColumn(Boolean value) {        
        return (value != null && value) ? "Y" : "N";            
        }    

    @Override
    public Boolean convertToEntityAttribute(String value) {
        return "Y".equals(value);
        }
    }

संपादित करें:

उपरोक्त कार्यान्वयन वर्ण "Y" से भिन्न कुछ भी मानता है, सहित null, जैसा कि false। क्या वो सही है? यहां कुछ लोग इसे गलत मानते हैं, और मानते हैं कि nullडेटाबेस nullमें जावा में होना चाहिए ।

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

और अगर आप nullअपवादों को स्वीकार करना चाहते हैं और छोड़ना चाहते हैं यदि डेटाबेस की सामग्री सख्ती से सही नहीं है, तो मुझे लगता है कि आपको "Y", "N" और के अलावा किसी भी वर्ण को स्वीकार नहीं करना चाहिए null। इसे सुसंगत बनाएं और "y", "n", "0" और "1" जैसी किसी भी विविधता को स्वीकार न करें, जो बाद में आपके जीवन को कठिन बना देगा। यह अधिक सख्त कार्यान्वयन है:

@Override
public String convertToDatabaseColumn(Boolean value) {
    if (value == null) return null;
    else return value ? "Y" : "N";
    }

@Override
public Boolean convertToEntityAttribute(String value) {
    if (value == null) return null;
    else if (value.equals("Y")) return true;
    else if (value.equals("N")) return false;
    else throw new IllegalStateException("Invalid boolean character: " + value);
    }

और फिर भी एक अन्य विकल्प, यदि आप nullजावा में अनुमति देना चाहते हैं लेकिन डेटाबेस में नहीं:

@Override
public String convertToDatabaseColumn(Boolean value) {
    if (value == null) return "-";
    else return value ? "Y" : "N";
    }

@Override
public Boolean convertToEntityAttribute(String value) {
    if (value.equals("-") return null;
    else if (value.equals("Y")) return true;
    else if (value.equals("N")) return false;
    else throw new IllegalStateException("Invalid boolean character: " + value);
    }

कनवर्टर विचार दिखाता है, लेकिन निश्चित रूप से काम नहीं कर रहा है। कनवर्टर Y, Nऔर के संभावित मूल्यों का उपयोग करता है T। मुझे यह भी निश्चित नहीं है कि रूपांतरण के परिणामस्वरूप शून्य मान होने के मामले को छोड़ देना चाहिए।
मथायस

@ मैथियास हां, टी टाइपो था। मैंने ठीक कर दिया। धन्यवाद।
मार्क जी

मेरे पास जेपीक्यूएल के साथ वाई / एन क्षेत्र का उपयोग करने का एक मुद्दा था और एक फॉलोअप प्रश्न यहां पोस्ट किया गया: stackoverflow.com/questions/39581225/…
क्रिस विलियम्स

11

मैंने @marcg द्वारा पोस्ट किए गए उत्तर से अवधारणा का उपयोग किया और यह जेपीए 2.1 के साथ बहुत अच्छा काम करता है। उनका कोड बिलकुल सही नहीं था, इसलिए मैंने अपना कार्यशील कार्यान्वयन पोस्ट किया है। यह Booleanइकाई फ़ील्ड्स को डेटाबेस में Y / N वर्ण स्तंभ में बदल देगा ।

मेरी इकाई वर्ग से:

@Convert(converter=BooleanToYNStringConverter.class)
@Column(name="LOADED", length=1)
private Boolean isLoadedSuccessfully;

मेरा कनवर्टर वर्ग:

/**
 * Converts a Boolean entity attribute to a single-character
 * Y/N string that will be stored in the database, and vice-versa
 * 
 * @author jtough
 */
public class BooleanToYNStringConverter 
        implements AttributeConverter<Boolean, String> {

    /**
     * This implementation will return "Y" if the parameter is Boolean.TRUE,
     * otherwise it will return "N" when the parameter is Boolean.FALSE. 
     * A null input value will yield a null return value.
     * @param b Boolean
     */
    @Override
    public String convertToDatabaseColumn(Boolean b) {
        if (b == null) {
            return null;
        }
        if (b.booleanValue()) {
            return "Y";
        }
        return "N";
    }

    /**
     * This implementation will return Boolean.TRUE if the string
     * is "Y" or "y", otherwise it will ignore the value and return
     * Boolean.FALSE (it does not actually look for "N") for any
     * other non-null string. A null input value will yield a null
     * return value.
     * @param s String
     */
    @Override
    public Boolean convertToEntityAttribute(String s) {
        if (s == null) {
            return null;
        }
        if (s.equals("Y") || s.equals("y")) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

}

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

/**
 * Converts a Boolean entity attribute to a happy face or sad face
 * that will be stored in the database, and vice-versa
 * 
 * @author jtough
 */
public class BooleanToHappySadConverter 
        implements AttributeConverter<Boolean, String> {

    public static final String HAPPY = ":)";
    public static final String SAD = ":(";

    /**
     * This implementation will return ":)" if the parameter is Boolean.TRUE,
     * otherwise it will return ":(" when the parameter is Boolean.FALSE. 
     * A null input value will yield a null return value.
     * @param b Boolean
     * @return String or null
     */
    @Override
    public String convertToDatabaseColumn(Boolean b) {
        if (b == null) {
            return null;
        }
        if (b) {
            return HAPPY;
        }
        return SAD;
    }

    /**
     * This implementation will return Boolean.TRUE if the string
     * is ":)", otherwise it will ignore the value and return
     * Boolean.FALSE (it does not actually look for ":(") for any
     * other non-null string. A null input value will yield a null
     * return value.
     * @param s String
     * @return Boolean or null
     */
    @Override
    public Boolean convertToEntityAttribute(String s) {
        if (s == null) {
            return null;
        }
        if (HAPPY.equals(s)) {
            return Boolean.TRUE;
        }
        return Boolean.FALSE;
    }

}

क्या unboxing 'b.booleanValue ()' आवश्यक है?
लियोन - हान ली

डेटाबेस वैल्यू के लिए NULLप्रॉपर्टी को छोड़कर NULL, यह उत्तर @MarKG उत्तर पर कोई वैल्यू ऐड नहीं प्रदान करता है। टिप्पणी के रूप में उस अंतर को पकड़ने के लिए सर्वश्रेष्ठ।
मोहनीश

आप 5 साल बहुत देर से कर रहे हैं
जिम कठिन

2

Y / N के लिए बेहतर बूलियन मैपिंग करने के लिए, अपने हाइबरनेट कॉन्फ़िगरेशन में जोड़ें:

<!-- when using type="yes_no" for booleans, the line below allow booleans in HQL expressions: -->
<property name="hibernate.query.substitutions">true 'Y', false 'N'</property>

अब आप HQL में बूलियन का उपयोग कर सकते हैं, उदाहरण के लिए:

"FROM " + SomeDomainClass.class.getName() + " somedomainclass " +
"WHERE somedomainclass.someboolean = false"

2
यह वैश्विक है। एकवचन गुणों के लिए पर्याप्त नहीं है।
मैक्सेक्सिम

0

गेट्टर एनोटेशन का उपयोग करके जेनेरिक तरीके से इसे करने के लिए, नीचे का उदाहरण हाइबरनेट 3.5.4 और ओरेकल 11 जी के साथ मेरे लिए काम करता है। ध्यान दें कि मैप किया गया गेटटर और सेटर ( getOpenedYnStringऔर setOpenedYnString) निजी तरीके हैं। वे विधियाँ मानचित्रण प्रदान करती हैं लेकिन कक्षा में सभी प्रोग्रामेटिक पहुँच getOpenedYnऔर setOpenedYnविधियों का उपयोग कर रही है ।

private String openedYn;

@Transient
public Boolean getOpenedYn() {
  return toBoolean(openedYn);
}

public void setOpenedYn(Boolean openedYn) {
  setOpenedYnString(toYesNo(openedYn));
}

@Column(name = "OPENED_YN", length = 1)
private String getOpenedYnString() {
  return openedYn;
}

private void setOpenedYnString(String openedYn) {
  this.openedYn = openedYn;
}

यहाँ स्थैतिक विधियों के साथ उपयोग वर्ग है toYesNoऔर toBoolean:

public class JpaUtil {

    private static final String NO = "N";
    private static final String YES = "Y";

    public static String toYesNo(Boolean value) {
        if (value == null)
            return null;
        else if (value)
            return YES;
        else
            return NO;
    }

    public static Boolean toBoolean(String yesNo) {
        if (yesNo == null)
            return null;
        else if (YES.equals(yesNo))
            return true;
        else if (NO.equals(yesNo))
            return false;
        else
            throw new RuntimeException("unexpected yes/no value:" + yesNo);
    }
}

-1

JPA 2.1 कन्वर्टर्स का उपयोग करना सबसे अच्छा समाधान है, हालांकि यदि आप JPA के पुराने संस्करण का उपयोग कर रहे हैं तो मैं एक और समाधान (या समाधान) की सिफारिश कर सकता हूं। T और F के 2 मानों के साथ BooleanWrapper नामक एक एनम बनाएं और लिपटे हुए मान प्राप्त करने के लिए निम्न विधि जोड़ें: public Boolean getValue() { return this == T; }@Enumerated (EnumType.STRING) के साथ इसे मैप करें।

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