मैं एक निरंतर संशोधन करने के लिए 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 में तत्वों के क्षेत्र का उपयोग करना आसान नहीं है
- यदि आप अपने डेटाबेस का समर्थन करते हैं, तो आप उपयुक्त कार्यों के साथ बाइनरी ऑपरेटरों या एक बिटमास्क कॉलम का उपयोग कर सकते हैं