मैं एक निरंतर संशोधन करने के लिए java.util.RegularEnumSet के एक मामूली संशोधन का उपयोग कर रहा हूं:
@MappedSuperclass
@Access(AccessType.FIELD)
public class PersistentEnumSet<E extends Enum<E>>
extends AbstractSet<E> {
private long elements;
@Transient
private final Class<E> elementType;
@Transient
private final E[] universe;
public PersistentEnumSet(final Class<E> elementType) {
this.elementType = elementType;
try {
this.universe = (E[]) elementType.getMethod("values").invoke(null);
} catch (final ReflectiveOperationException e) {
throw new IllegalArgumentException("Not an enum type: " + elementType, e);
}
if (this.universe.length > 64) {
throw new IllegalArgumentException("More than 64 enum elements are not allowed");
}
}
}
यह वर्ग अब मेरे सभी एनम सेट के लिए आधार है:
@Embeddable
public class InterestsSet extends PersistentEnumSet<InterestsEnum> {
public InterestsSet() {
super(InterestsEnum.class);
}
}
और वह सेट मैं अपनी इकाई में उपयोग कर सकता हूं:
@Entity
public class MyEntity {
@Embedded
@AttributeOverride(name="elements", column=@Column(name="interests"))
private InterestsSet interests = new InterestsSet();
}
लाभ:
- आपके कोड में सेट एक प्रकार के सुरक्षित और प्रदर्शनकारी एनम के साथ काम करना (
java.util.EnumSetविवरण के लिए देखें )
- सेट डेटाबेस में सिर्फ एक संख्यात्मक कॉलम है
- सब कुछ सादा जेपीए है (कोई प्रदाता विशिष्ट कस्टम प्रकार नहीं )
- अन्य समाधानों की तुलना में एक ही प्रकार के नए क्षेत्रों की आसान (और छोटी) घोषणा
कमियां:
- कोड दोहराव (
RegularEnumSet और PersistentEnumSetलगभग समान हैं)
- आप
EnumSet.noneOf(enumType)अपने परिणाम को रैप कर सकते हैं PersistenEnumSet, घोषित कर सकते हैं AccessType.PROPERTYऔर दो एक्सेस तरीके प्रदान कर सकते हैं जो पढ़ने और लिखने के लिए प्रतिबिंब का उपयोग करते हैंelements फील्ड हैं
- प्रत्येक enum वर्ग के लिए एक अतिरिक्त सेट क्लास की आवश्यकता होती है जिसे एक स्थिर सेट में संग्रहीत किया जाना चाहिए
- यदि आपका दृढ़ता प्रदाता सार्वजनिक निर्माणकर्ता के बिना एम्बेड का समर्थन करता है, तो आप अतिरिक्त वर्ग
@Embeddableको जोड़ सकते हैं PersistentEnumSetऔर छोड़ सकते हैं ( ... interests = new PersistentEnumSet<>(InterestsEnum.class);)
- आपको एक का उपयोग करना चाहिए
@AttributeOverride मेरे उदाहरण में दिए गए , यदि आपको PersistentEnumSetअपनी इकाई में एक से अधिक मिला है (अन्यथा दोनों को एक ही कॉलम "तत्वों" में संग्रहीत किया जाएगा)
- की पहुँच
values()कंस्ट्रक्टर में प्रतिबिंब साथ इष्टतम नहीं है (विशेषकर जब प्रदर्शन को देखते हुए), लेकिन दो अन्य विकल्पों में उनकी कमियां भी हैं:
- एक कार्यान्वयन की तरह एक का
EnumSet.getUniverse()उपयोग करता हैsun.misc वर्ग
- मान सरणी को पैरामीटर के रूप में प्रदान करना जोखिम है कि दिए गए मान सही नहीं हैं
- केवल 64 मान वाले एनम का समर्थन किया जाता है (क्या यह वास्तव में एक खामी है?)
- आप इसके बजाय BigInteger का उपयोग कर सकते हैं
- मापदंड क्वेरी या JPQL में तत्वों के क्षेत्र का उपयोग करना आसान नहीं है
- यदि आप अपने डेटाबेस का समर्थन करते हैं, तो आप उपयुक्त कार्यों के साथ बाइनरी ऑपरेटरों या एक बिटमास्क कॉलम का उपयोग कर सकते हैं