我对java.util稍作修改。RegularEnumSet有一个持久的EnumSet:
@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");
}
}
// Copy everything else from java.util.RegularEnumSet
// ...
}
现在这个类是我所有的枚举集基地:
@Embeddable
public class InterestsSet extends PersistentEnumSet<InterestsEnum> {
public InterestsSet() {
super(InterestsEnum.class);
}
}
这一套,我可以在我的实体使用:
@Entity
public class MyEntity {
// ...
@Embedded
@AttributeOverride(name="elements", [email protected](name="interests"))
private InterestsSet interests = new InterestsSet();
}
优点:
- 在你的代码类型安全和高性能的枚举集工作(参见
java.util.EnumSet
的描述)
- 集是在数据库中只有一个数字列
- 一切都是原生的JPA(没有提供具体自定义类型)
- 容易(和短)的相同类型的新的字段声明,与其他解决方案
缺点相比:
- 代码重复(
RegularEnumSet
和PersistentEnumSet
几乎相同)
- 你可以换的
EnumSet.noneOf(enumType)
结果在PersistenEnumSet
,声明AccessType.PROPERTY
并提供使用反射两种接入方式来读取和写入elements
场
- 对于应存储在持久集中的每个枚举类,需要额外的集合类
- 如果您的持久性提供者支持TS embeddables没有公共构造函数,你可以添加到
@Embeddable
和PersistentEnumSet
降 额外的类(... interests = new PersistentEnumSet<>(InterestsEnum.class);
)
- 您必须使用
@AttributeOverride
,因为在我的例子给出的,如果你有一个以上的PersistentEnumSet
在你的实体(否则两者都将被存储到同一列“元素”)
values()
与反射在构造函数中的访问不是最优的(尤其是在查看性能时),但其他两个选项也有它们的缺点:
- 一个工具像
EnumSet.getUniverse()
通货膨胀利用的sun.misc
类
- 提供了值数组作为参数具有风险,即给定值是不正确的参数
- 只有拥有多达64个值枚举的支持(是真的退税?)
- 这是不容易的使用条件查询元素域或JPQL
- 如果你可以用二元运算符或相应的功能位掩码列,您数据库支持
如果有人现在阅读此文件... @CollectionOfElements现在已被弃用,请改为使用:@ElementCollection – 2010-04-21 16:59:42
您可以在此问题的答案中找到示例:http://stackoverflow.com/q/3152787/363573 – Stephan 2011-08-13 22:24:29
既然你上面提到的Hibernate,我认为这个答案可能是特定于供应商的,但我不认为它是这样的,除非在其他实现中使用JoinTable会导致麻烦。从我所看到的,我相信应该使用CollectionTable。这就是我在我的答案中使用的,它适用于我(尽管是的,我现在也在使用Hibernate)。 – spaaarky21 2012-03-05 20:51:59