निश्चित मूल्यों के साथ जेपीए में नक्शा संलग्न करें?


192

मैं JPA का उपयोग करके एनम को मैप करने के विभिन्न तरीकों की तलाश कर रहा हूं। मैं विशेष रूप से प्रत्येक एनम प्रविष्टि के पूर्णांक मान को सेट करना चाहता हूं और केवल पूर्णांक मान को बचाना चाहता हूं।

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

  public enum Right {
      READ(100), WRITE(200), EDITOR (300);

      private int value;

      Right(int value) { this.value = value; }

      public int getValue() { return value; }
  };

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "AUTHORITY_ID")
  private Long id;

  // the enum to map : 
  private Right right;
}

एक सरल उपाय EnumType.ORDINAL के साथ एन्यूमरेटेड एनोटेशन का उपयोग करना है:

@Column(name = "RIGHT")
@Enumerated(EnumType.ORDINAL)
private Right right;

लेकिन इस मामले में जेपीए एनुम इंडेक्स (0,1,2) का नक्शा बनाता है, न कि वह मूल्य जो मैं चाहता हूं (100,200,300)।

गु दो समाधान मुझे लगता है कि सरल नहीं लगता ...

पहला उपाय

यहाँ प्रस्तावित एक समाधान, @PrePersist और @PostLoad का उपयोग करता है कि एनम को दूसरे क्षेत्र में बदलने के लिए और एनीम क्षेत्र को क्षणिक के रूप में चिह्नित करें:

@Basic
private int intValueForAnEnum;

@PrePersist
void populateDBFields() {
  intValueForAnEnum = right.getValue();
}

@PostLoad
void populateTransientFields() {
  right = Right.valueOf(intValueForAnEnum);
}

दूसरा उपाय

यहाँ प्रस्तावित दूसरा समाधान एक सामान्य रूपांतरण वस्तु का प्रस्ताव करता है, लेकिन फिर भी भारी और हाइबरनेट-उन्मुख लगता है (@ टाइप जावा ईई में मौजूद नहीं है):

@Type(
    type = "org.appfuse.tutorial.commons.hibernate.GenericEnumUserType",
    parameters = {
            @Parameter(
                name  = "enumClass",                      
                value = "Authority$Right"),
            @Parameter(
                name  = "identifierMethod",
                value = "toInt"),
            @Parameter(
                name  = "valueOfMethod",
                value = "fromInt")
            }
)

क्या कोई और उपाय है?

मेरे मन में कई विचार हैं लेकिन मुझे नहीं पता कि क्या वे JPA में मौजूद हैं:

  • प्राधिकरण ऑब्जेक्ट को लोड और सहेजते समय प्राधिकारी वर्ग के सेटर और गेट्टर विधियों का उपयोग करें
  • समतुल्य विचार जेपीए को यह बताने के लिए होगा कि एनम को अंतर में और एनम को एनुम में बदलने के लिए राइट इनम के तरीके क्या हैं
  • क्योंकि मैं स्प्रिंग का उपयोग कर रहा हूं, क्या जेपीए को एक विशिष्ट कनवर्टर (राइटएडिटर) का उपयोग करने का कोई तरीका है?

7
ORDINAL का उपयोग करना अजीब है। कभी-कभी गणन में वस्तुओं के स्थान बदल जाएंगे और डेटाबेस आपदा बन जाएगा
नताशा केपी

2
नाम का उपयोग करने के लिए समान लागू नहीं होगा - कोई व्यक्ति
एनम

2
मैं @NatashaKP से सहमत हूं। क्रमिक उपयोग न करें। नाम बदलने के लिए, ऐसी कोई बात नहीं है। आप वास्तव में पुरानी एनम को हटा रहे हैं और एक नए नाम के साथ एक नया जोड़ रहे हैं, इसलिए हां, कोई भी संग्रहीत डेटा सिंक से बाहर होगा (शब्दार्थ, शायद: पी)।
स्वेन्द हेन्सन

हाँ वहाँ 5 समाधान हैं जो मुझे पता है। मेरा जवाब नीचे देखें, जहां मेरे पास एक विस्तृत जवाब है।
क्रिस रिची

जवाबों:


168

जेपीए 2.1 की तुलना में पहले के संस्करणों के लिए, जेपीए अपने nameया उनके द्वारा, दुश्मनी से निपटने के लिए केवल दो तरीके प्रदान करता है ordinal। और मानक JPA कस्टम प्रकारों का समर्थन नहीं करता है। इसलिए:

  • यदि आप कस्टम प्रकार के रूपांतरण करना चाहते हैं, तो आपको एक प्रदाता एक्सटेंशन (हाइबरनेट UserType, एक्लिप्सलिंक Converter, आदि के साथ) का उपयोग करना होगा। (दूसरा उपाय)। ~ या ~
  • आपको @PrePersist और @PostLoad ट्रिक (पहला समाधान) का उपयोग करना होगा। ~ या ~
  • intमान ~ और ~ लेने और वापस करने वाले गेटर और सेटर को एनोटेट करें
  • इकाई स्तर पर एक पूर्णांक विशेषता का उपयोग करें और गेटर्स और सेटर में अनुवाद करें।

मैं नवीनतम विकल्प का वर्णन करूँगा (यह एक मूल कार्यान्वयन है, इसे आवश्यकतानुसार ट्विक करें):

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

    public enum Right {
        READ(100), WRITE(200), EDITOR (300);

        private int value;

        Right(int value) { this.value = value; }    

        public int getValue() { return value; }

        public static Right parse(int id) {
            Right right = null; // Default
            for (Right item : Right.values()) {
                if (item.getValue()==id) {
                    right = item;
                    break;
                }
            }
            return right;
        }

    };

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "AUTHORITY_ID")
    private Long id;

    @Column(name = "RIGHT_ID")
    private int rightId;

    public Right getRight () {
        return Right.parse(this.rightId);
    }

    public void setRight(Right right) {
        this.rightId = right.getValue();
    }

}

50
इतना दुखी जेपीए के पास इसके लिए मूल समर्थन नहीं है
जेम हैबटलज़ेल

20
@ लाइम सहमत! क्या यह सोचना पागल है कि डेवलपर्स एक एनम को अपने अंतर मूल्य या नाम के बजाय अपने किसी फ़ील्ड / गुण के मान के रूप में जारी रखना चाहते हैं? वे दोनों बेहद "नाजुक" और refactoring-unfriendly हैं। और नाम का उपयोग भी मानता है कि आप जावा और डेटाबेस दोनों में समान नामकरण सम्मेलन का उपयोग कर रहे हैं। उदाहरण के लिए लिंग लें। इसे डेटाबेस में केवल 'M' या 'F' के रूप में परिभाषित किया जा सकता है, लेकिन इससे मुझे Gender.Male और Gender.F के बजाय Java में Gender.MALE और Gender.FEMALE का उपयोग करने से नहीं रोकना चाहिए।
स्पाकार्की 21

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

2
वास्तव में, मैं मूल्य देखता हूं ... मैं अपनी टिप्पणी के उस हिस्से को हटा दूंगा, अगर मैं अभी भी इसे संपादित कर सकता हूं: P: D
Svend Hansen

13
JPA2.1 में कनवर्टर का समर्थन मूल रूप से होगा। कृपया देखें somethoughtsonjava.blogspot.fi/2013/10/…
दिनांक 7

69

यह अब जेपीए 2.1 के साथ संभव है:

@Column(name = "RIGHT")
@Enumerated(EnumType.STRING)
private Right right;

आगे की जानकारी:


2
अब क्या संभव है? यकीन है कि हम उपयोग कर सकते हैं @Converter, लेकिन enumअधिक सुरुचिपूर्ण ढंग से बॉक्स से बाहर संभाला जाना चाहिए!
योयो

4
"उत्तर" संदर्भ 2 लिंक जो एक AttributeConverterBUT का उपयोग करने की बात करते हैं, कुछ कोड को उद्धृत करते हैं जो ओप का जवाब नहीं देते हैं।

@ डीएन 1 इसे सुधारने के लिए स्वतंत्र महसूस करता है
तवरोह

1
यह आपका "उत्तर" है, इसलिए आपको "इसे सुधारना" चाहिए। पहले से ही एक उत्तर हैAttributeConverter

1
जोड़ने के बाद पूरी तरह से काम कर रहा है:@Convert(converter = Converter.class) @Enumerated(EnumType.STRING)
कौशल

23

JPA 2.1 से आप AttributeConverter का उपयोग कर सकते हैं ।

एक एनुमरेटेड क्लास बनाएं जैसे:

public enum NodeType {

    ROOT("root-node"),
    BRANCH("branch-node"),
    LEAF("leaf-node");

    private final String code;

    private NodeType(String code) {
        this.code = code;
    }

    public String getCode() {
        return code;
    }
}

और इस तरह एक कनवर्टर बनाएँ:

import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

@Converter(autoApply = true)
public class NodeTypeConverter implements AttributeConverter<NodeType, String> {

    @Override
    public String convertToDatabaseColumn(NodeType nodeType) {
        return nodeType.getCode();
    }

    @Override
    public NodeType convertToEntityAttribute(String dbData) {
        for (NodeType nodeType : NodeType.values()) {
            if (nodeType.getCode().equals(dbData)) {
                return nodeType;
            }
        }

        throw new IllegalArgumentException("Unknown database value:" + dbData);
    }
}

इकाई पर आपको बस जरूरत है:

@Column(name = "node_type_code")

आप @Converter(autoApply = true)कंटेनर से भिन्न हो सकते हैं लेकिन वाइल्डफ्लाइ 8.1.0 पर काम करने के लिए परीक्षण किया जा सकता है। यदि यह काम नहीं करता है तो आप @Convert(converter = NodeTypeConverter.class)इकाई वर्ग कॉलम में जोड़ सकते हैं ।


"मान ()" होना चाहिए "NodeType.values ​​()"
कर्टिस

17

सबसे अच्छा तरीका यह होगा कि प्रत्येक एनुम प्रकार के लिए एक अद्वितीय आईडी मैप किया जाए, इस प्रकार ORDINAL और STRING के नुकसान से बचा जा सकता है। इस पोस्ट को देखें जिसमें 5 तरीके हैं जिनसे आप एक एनम का नक्शा बना सकते हैं।

ऊपर दिए गए लिंक से लिया गया:

1 और 2। @Enumerated का उपयोग करना

वर्तमान में 2 तरीके हैं जिनसे आप अपने JPA संस्थाओं में @Enumerated एनोटेशन का उपयोग करके मैप कर सकते हैं। दुर्भाग्य से EnumType.STRING और EnumType.ORDINAL दोनों की अपनी सीमाएँ हैं।

यदि आप EnumType.String का उपयोग करते हैं, तो आपके एक Enum प्रकार का नाम बदलने से आपके Enum मान डेटाबेस में सहेजे गए मानों के साथ सिंक से बाहर हो जाएगा। यदि आप EnumType.ORDINAL का उपयोग करते हैं तो आपके Enum के भीतर के प्रकारों को हटाने या फिर से व्यवस्थित करने से डेटाबेस में सहेजे गए मान गलत enums प्रकारों में मैप हो जाएंगे।

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

3. जीवनचक्र कॉलबैक

JPA जीवनचक्र कॉल बैक एनोटेशन, @PrePersist और @PostLoad का उपयोग करने के लिए एक संभावित समाधान होगा। यह काफी बदसूरत लगता है क्योंकि अब आपकी इकाई में दो चर होंगे। एक डेटाबेस में संग्रहीत मूल्य का मानचित्रण, और दूसरा, वास्तविक एनम।

4. प्रत्येक एनुम प्रकार के लिए अद्वितीय आईडी का मानचित्रण

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

5. Java EE7 @Convert का उपयोग करना

यदि आप JPA 2.1 का उपयोग कर रहे हैं तो आपके पास नए @Convert एनोटेशन का उपयोग करने का विकल्प है। इसके लिए एक कनवर्टर वर्ग के निर्माण की आवश्यकता है, जो @Converter के साथ एनोटेट किया गया है, जिसके अंदर आप परिभाषित करेंगे कि प्रत्येक एनम प्रकार के लिए डेटाबेस में कौन से मान सहेजे गए हैं। तब आपकी इकाई के भीतर आप @ एनकॉनट के साथ अपने एनम को एनोटेट करेंगे।

मेरी प्राथमिकता: (संख्या 4)

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

कोड उदाहरण के लिए मूल पोस्ट देखें ।


1
javax.persistence.Converter सरल है और @Converter (autoApply = true) के साथ यह डोमेन कक्षाओं को @Convert एनोटेशन से मुक्त रखने की अनुमति देता है
Matl

9

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

मुझे लगता है कि एनुम के लिए विशिष्ट, इसके परिणामस्वरूप दो मुख्य कमियां हैं:

  1. नाम () और अध्यादेश () का उपयोग करने की सीमा। क्यों न हम @Id के साथ एक गेट्टर को चिह्नित करें, जिस तरह से हम @Entity के साथ करते हैं?
  2. Enum का आमतौर पर डेटाबेस में सभी प्रकार के मेटाडेटा के साथ सहयोग करने की अनुमति है, जिसमें एक उचित नाम, एक वर्णनात्मक नाम, शायद स्थानीयकरण के साथ कुछ शामिल है आदि। हमें एक इकाई के लचीलेपन के साथ संयुक्त Enum के उपयोग की आवश्यकता है।

मेरे कारण की मदद करें और JPA_SPEC-47 पर वोट करें

क्या यह समस्या को हल करने के लिए एक @ कनेक्टर का उपयोग करने से अधिक सुरुचिपूर्ण नहीं होगा?

// Note: this code won't work!!
// it is just a sample of how I *would* want it to work!
@Enumerated
public enum Language {
  ENGLISH_US("en-US"),
  ENGLISH_BRITISH("en-BR"),
  FRENCH("fr"),
  FRENCH_CANADIAN("fr-CA");
  @ID
  private String code;
  @Column(name="DESCRIPTION")
  private String description;

  Language(String code) {
    this.code = code;
  }

  public String getCode() {
    return code;
  }

  public String getDescription() {
    return description;
  }
}

4

संभवतः पास्कल के संबंधित कोड

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {

    public enum Right {
        READ(100), WRITE(200), EDITOR(300);

        private Integer value;

        private Right(Integer value) {
            this.value = value;
        }

        // Reverse lookup Right for getting a Key from it's values
        private static final Map<Integer, Right> lookup = new HashMap<Integer, Right>();
        static {
            for (Right item : Right.values())
                lookup.put(item.getValue(), item);
        }

        public Integer getValue() {
            return value;
        }

        public static Right getKey(Integer value) {
            return lookup.get(value);
        }

    };

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "AUTHORITY_ID")
    private Long id;

    @Column(name = "RIGHT_ID")
    private Integer rightId;

    public Right getRight() {
        return Right.getKey(this.rightId);
    }

    public void setRight(Right right) {
        this.rightId = right.getValue();
    }

}

3

मैं फोलोइंग करूंगा:

यह फ़ाइल में अलग-अलग enum की घोषणा करें:

public enum RightEnum {
      READ(100), WRITE(200), EDITOR (300);

      private int value;

      private RightEnum (int value) { this.value = value; }


      @Override
      public static Etapa valueOf(Integer value){
           for( RightEnum r : RightEnum .values() ){
              if ( r.getValue().equals(value))
                 return r;
           }
           return null;//or throw exception
     }

      public int getValue() { return value; }


}

एक नई JPA इकाई घोषित करें जिसका नाम राइट है

@Entity
public class Right{
    @Id
    private Integer id;
    //FIElDS

    // constructor
    public Right(RightEnum rightEnum){
          this.id = rightEnum.getValue();
    }

    public Right getInstance(RightEnum rightEnum){
          return new Right(rightEnum);
    }


}

आपको इस मान को प्राप्त करने के लिए एक कनवर्टर की भी आवश्यकता होगी (केवल JPA 2.1 और इसके साथ ही I’ll समस्या पर चर्चा नहीं की जाएगी, इन enum directlys के साथ सीधे कनवर्टर का उपयोग करके बनाए रखने के लिए, इसलिए यह केवल एक रास्ता होगा)

import mypackage.RightEnum;
import javax.persistence.AttributeConverter;
import javax.persistence.Converter;

/**
 * 
 * 
 */
@Converter(autoApply = true)
public class RightEnumConverter implements AttributeConverter<RightEnum, Integer>{

    @Override //this method shoudn´t be used, but I implemented anyway, just in case
    public Integer convertToDatabaseColumn(RightEnum attribute) {
        return attribute.getValue();
    }

    @Override
    public RightEnum convertToEntityAttribute(Integer dbData) {
        return RightEnum.valueOf(dbData);
    }

}

प्राधिकरण इकाई:

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {


  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "AUTHORITY_ID")
  private Long id;

  // the **Entity** to map : 
  private Right right;

  // the **Enum** to map (not to be persisted or updated) : 
  @Column(name="COLUMN1", insertable = false, updatable = false)
  @Convert(converter = RightEnumConverter.class)
  private RightEnum rightEnum;

}

इस तरह से, आप सीधे एनम फील्ड पर सेट कर सकते हैं। हालाँकि, आप अधिकार क्षेत्र का उपयोग करके प्राधिकरण में सेट कर सकते हैं

autorithy.setRight( Right.getInstance( RightEnum.READ ) );//for example

और अगर आपको तुलना करने की आवश्यकता है, तो आप उपयोग कर सकते हैं:

authority.getRight().equals( RightEnum.READ ); //for example

मुझे लगता है कि बहुत अच्छा है। यह पूरी तरह से सही नहीं है, क्योंकि कनवर्टर itums के साथ उपयोग करने का इरादा नहीं है। दरअसल, प्रलेखन कहता है कि इस उद्देश्य के लिए इसका उपयोग कभी न करें, आपको इसके बजाय @Enumerated एनोटेशन का उपयोग करना चाहिए। समस्या यह है कि केवल दो प्रकार के हैं: ORDINAL या STRING, लेकिन ORDINAL मुश्किल है और सुरक्षित नहीं है।


हालांकि, अगर यह आपको संतुष्ट नहीं करता है, तो आप कुछ अधिक हैसी और सरल (या नहीं) कर सकते हैं।

चलो देखते हैं।

अधिकार:

public enum RightEnum {
      READ(100), WRITE(200), EDITOR (300);

      private int value;

      private RightEnum (int value) { 
            try {
                  this.value= value;
                  final Field field = this.getClass().getSuperclass().getDeclaredField("ordinal");
                  field.setAccessible(true);
                  field.set(this, value);
             } catch (Exception e) {//or use more multicatch if you use JDK 1.7+
                  throw new RuntimeException(e);
            }
      }


      @Override
      public static Etapa valueOf(Integer value){
           for( RightEnum r : RightEnum .values() ){
              if ( r.getValue().equals(value))
                 return r;
           }
           return null;//or throw exception
     }

      public int getValue() { return value; }


}

और प्राधिकरण इकाई

@Entity
@Table(name = "AUTHORITY_")
public class Authority implements Serializable {


  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  @Column(name = "AUTHORITY_ID")
  private Long id;


  // the **Enum** to map (to be persisted or updated) : 
  @Column(name="COLUMN1")
  @Enumerated(EnumType.ORDINAL)
  private RightEnum rightEnum;

}

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

मुझे लगता है कि जेपीए विनिर्देश में EnumType.ID को शामिल करना चाहिए जहां Enum मान फ़ील्ड को कुछ प्रकार के @EnumId एनोटेशन के साथ एनोटेट किया जाना चाहिए।


2

इस तरह के Enum JPA मानचित्रण को हल करने के लिए मेरा अपना समाधान निम्नलिखित है।

चरण 1 - निम्नलिखित इंटरफ़ेस लिखें, जिसका उपयोग हम उन सभी एनमों के लिए करेंगे, जिन्हें हम db कॉलम में मैप करना चाहते हैं:

public interface IDbValue<T extends java.io.Serializable> {

    T getDbVal();

}

चरण 2 - एक सामान्य जेपीए कनवर्टर को निम्नानुसार लागू करें:

import javax.persistence.AttributeConverter;

public abstract class EnumDbValueConverter<T extends java.io.Serializable, E extends Enum<E> & IDbValue<T>>
        implements AttributeConverter<E, T> {

    private final Class<E> clazz;

    public EnumDbValueConverter(Class<E> clazz){
        this.clazz = clazz;
    }

    @Override
    public T convertToDatabaseColumn(E attribute) {
        if (attribute == null) {
            return null;
        }
        return attribute.getDbVal();
    }

    @Override
    public E convertToEntityAttribute(T dbData) {
        if (dbData == null) {
            return null;
        }
        for (E e : clazz.getEnumConstants()) {
            if (dbData.equals(e.getDbVal())) {
                return e;
            }
        }
        // handle error as you prefer, for example, using slf4j:
        // log.error("Unable to convert {} to enum {}.", dbData, clazz.getCanonicalName());
        return null;
    }

}

इस वर्ग enum मूल्य में परिवर्तित कर देंगे Eप्रकार के एक डेटाबेस क्षेत्र के लिए T(उदाहरण के लिए Stringका उपयोग करके) getDbVal()enum पर E, और इसके विपरीत।

चरण 3 - मूल एनम को हम चरण 1 में परिभाषित इंटरफ़ेस को लागू करने दें:

public enum Right implements IDbValue<Integer> {
    READ(100), WRITE(200), EDITOR (300);

    private final Integer dbVal;

    private Right(Integer dbVal) {
        this.dbVal = dbVal;
    }

    @Override
    public Integer getDbVal() {
        return dbVal;
    }
}

चरण 4 - Rightचरण 3 की गणना के लिए चरण 2 के कनवर्टर का विस्तार करें :

public class RightConverter extends EnumDbValueConverter<Integer, Right> {
    public RightConverter() {
        super(Right.class);
    }
}

चरण 5 - अंतिम चरण इकाई में फ़ील्ड को एनोटेट करने के लिए निम्नानुसार है:

@Column(name = "RIGHT")
@Convert(converter = RightConverter.class)
private Right right;

निष्कर्ष

IMHO यह सबसे साफ और सबसे सुंदर समाधान है यदि आपके पास नक्शे के लिए बहुत सारे हैं और आप मैपिंग मूल्य के रूप में एनम के एक विशेष क्षेत्र का उपयोग करना चाहते हैं।

अपनी परियोजना के सभी अन्य लोगों के लिए, जिन्हें समान मानचित्रण तर्क की आवश्यकता है, आपको केवल चरण 3 से 5 को दोहराना होगा, अर्थात:

  • IDbValueअपने एनम पर इंटरफ़ेस लागू करें ;
  • EnumDbValueConverterकोड की केवल 3 लाइनों के साथ विस्तार करें (आप एक अलग वर्ग बनाने से बचने के लिए अपनी इकाई के भीतर भी ऐसा कर सकते हैं);
  • पैकेज @Convertसे एनम विशेषता एनोटेट करें javax.persistence

उम्मीद है की यह मदद करेगा।


1
public enum Gender{ 
    MALE, FEMALE 
}



@Entity
@Table( name="clienti" )
public class Cliente implements Serializable {
...

// **1 case** - If database column type is number (integer) 
// (some time for better search performance)  -> we should use 
// EnumType.ORDINAL as @O.Badr noticed. e.g. inserted number will
// index of constant starting from 0... in our example for MALE - 0, FEMALE - 1.
// **Possible issue (advice)**: you have to add the new values at the end of
// your enum, in order to keep the ordinal correct for future values.

@Enumerated(EnumType.ORDINAL)
    private Gender gender;


// **2 case** - If database column type is character (varchar) 
// and you want to save it as String constant then ->

@Enumerated(EnumType.STRING)
    private Gender gender;

...
}

// in all case on code level you will interact with defined 
// type of Enum constant but in Database level

पहला मामला ( EnumType.ORDINAL)

╔════╦══════════════╦════════╗
 ID     NAME       GENDER 
╠════╬══════════════╬════════╣
  1  Jeff Atwood      0   
  2  Geoff Dalgas     0   
  3 Jarrod Jesica     1   
  4  Joel Lucy        1   
╚════╩══════════════╩════════╝

दूसरा मामला ( EnumType.STRING)

╔════╦══════════════╦════════╗
 ID     NAME       GENDER 
╠════╬══════════════╬════════╣
  1  Jeff Atwood    MALE  
  2  Geoff Dalgas   MALE  
  3 Jarrod Jesica  FEMALE 
  4  Joel Lucy     FEMALE 
╚════╩══════════════╩════════╝
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.