Kalıcı bir EnumSet'e sahip olmak için java.util.RegularEnumSet'in küçük bir değişikliğini kullanıyorum:
@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");
}
}
}
Bu sınıf artık tüm sıralama kümelerimin temelini oluşturuyor:
@Embeddable
public class InterestsSet extends PersistentEnumSet<InterestsEnum> {
public InterestsSet() {
super(InterestsEnum.class);
}
}
Ve varlığımda kullanabileceğim bu set:
@Entity
public class MyEntity {
@Embedded
@AttributeOverride(name="elements", column=@Column(name="interests"))
private InterestsSet interests = new InterestsSet();
}
Avantajlar:
- Kodunuzda bir tür güvenli ve performanslı enum kümesiyle çalışma (
java.util.EnumSet
açıklama için bakın )
- Küme, veritabanında yalnızca bir sayısal sütundur
- her şey düz JPA'dır (sağlayıcıya özgü özel türler yoktur )
- diğer çözümlere kıyasla aynı türdeki yeni alanların kolay (ve kısa) beyanı
Dezavantajlar:
- Kod çoğaltma (
RegularEnumSet
ve PersistentEnumSet
neredeyse aynıdır)
- Sen sonucunu sarabilirdiniz
EnumSet.noneOf(enumType)
senin içinde PersistenEnumSet
, bir açıklamadan AccessType.PROPERTY
ve okumak için yansıma kullanan iki erişim yöntemlerini sağlamak ve yazma elements
alanı
- Kalıcı bir kümede depolanması gereken her enum sınıfı için ek bir küme sınıfı gereklidir.
- Senin kalıcılık sağlayıcısı kamu yapıcı olmayan embeddables destekliyorsa, ekleyebilir
@Embeddable
için PersistentEnumSet
(ve ekstra sınıfı bırakmak ... interests = new PersistentEnumSet<>(InterestsEnum.class);
)
@AttributeOverride
Varlığınızda birden fazla varsa, örneğimde verildiği gibi bir kullanmalısınız PersistentEnumSet
(aksi takdirde her ikisi de aynı sütun "öğeler" içinde saklanır)
values()
Yapıcıda yansımalı erişim optimal değildir (özellikle performansa bakıldığında), ancak diğer iki seçeneğin de dezavantajları vardır:
- Bir sınıftan
EnumSet.getUniverse()
yararlanan gibi bir uygulamasun.misc
- Değerler dizisinin parametre olarak sağlanması, verilen değerlerin doğru değerler olmaması riskini taşır.
- Yalnızca 64 değere kadar numaralandırmalar desteklenir (bu gerçekten bir dezavantaj mı?)
- Bunun yerine BigInteger kullanabilirsiniz
- Öğeler alanını bir ölçüt sorgusunda veya JPQL'de kullanmak kolay değildir
- Veritabanınız destekliyorsa, uygun işlevlerle ikili operatörler veya bir bit maskesi sütunu kullanabilirsiniz.