如何在hibernate中存储枚举数组



我正在尝试使用Hibernate持久化一个枚举数组。需要注意的是,如果可能的话,我宁愿不使用集合。到目前为止,我在网上找到的答案是存储集合,而不是数组。

我收到一个运行时错误,抱怨缺少@OrderColumn或@IndexColumn。我不希望数组按字母顺序排列。我希望按同样的顺序退货。

枚举实际上和你要求的一样简单,但enum.name()不是按字母顺序排列的,所以似乎没有自然的"顺序"列。

@Embeddable
public enum SudokuPossibleValueState {
UNDEFINED, UNKNOWN, IMPOSSIBLE, POSSIBLE, COMMITTED, AS_PUBLISHED;
public String toString() {
return name().toLowerCase();
}
}

根据定义,我使用数组中的实际位置来指示我正在考虑的数字,枚举定义了该数字的求值状态。例如,一个典型的数组可能是。。。

[0] = UNDEFINED, 
[1] = UNDEFINED, 
[2] = POSSIBLE, 
[3] = POSSIBLE, 
[4] = UNKNOWN, 
[5] = UNKNOWN, 
[6] = UNKNOWN, 
[7] = IMPOSSIBLE, 
[8] = IMPOSSIBLE,
[9] = IMPOSSIBLE.

但我遇到的挑战是,我可以在网上找到的所有例子,以及Hibernate文档,似乎都只是针对使用Java集合的情况;这不是我想要做的。

@Entity
@Table(name = "SudokuPossibleValues")
public class SudokuPossibleValuesModel {   
public static final int NUMBER_OF_POSSIBLE_VALUES_PLUS_ONE = 10;
@Id
@GeneratedValue
private long possibleValuesID;
@ElementCollection
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState stateValues[] = new SudokuPossibleValueState[NUMBER_OF_POSSIBLE_VALUES_PLUS_ONE];
...
}

答案迟了,但我也做了同样的事情,并创建了这个类:

public abstract class EEnumArrayAttributeConverter<E extends Enum<E>> implements AttributeConverter<E[], String> {
private static final String DIVIDER = "|";
private final Class<E> classEnum;
protected EEnumArrayAttributeConverter(final Class<E> classEnum) {
this.classEnum = classEnum; 
}

@Override
public String convertToDatabaseColumn(final E[] values) {
String retVal = "";
if (null != values) {
for (final E value : values) {
if (!retVal.isEmpty()) {
retVal += DIVIDER;
}
retVal += value.name();
}
}
return retVal;
}
protected abstract E[] create(final int size);

@Override
public E[] convertToEntityAttribute(final String str) {
if ((null == str) || str.isEmpty()) {
return create(0);
}
else {
final String[] parts = str.split("\"+ DIVIDER);
final E[] retVal = create(parts.length);
for (int x = 0; x < parts.length; x++) {
retVal[x] = E.valueOf(classEnum, parts[x]);
}
return retVal;
}
}
}

然后,您可以将转换器实现为:

public class ESudokuPossibleValueStateArrayAttributeConverter extends EEnumArrayAttributeConverter<SudokuPossibleValueState> {
public ESudokuPossibleValueStateArrayAttributeConverter() {
super(SudokuPossibleValueState.class);
}
@Override
protected SudokuPossibleValueState[] create(int size) {
return new SudokuPossibleValueState[size];
}
}

然后在你的课堂上:

@Convert(converter = ESudokuPossibleValueStateArrayAttributeConverter.class)
private SudokuPossibleValueState stateValues[];

我给出了一个答案,但请告诉我在JPA或Hibernate中有更好的方法可以做到这一点。

@Entity
@Table(name = "POSSIBLE_VALUES")
public class PossibleValues {
@SuppressWarnings("unused")
private static final long serialVersionUID                   = -1L;    
public static final int   NUMBER_OF_POSSIBLE_VALUES_PLUS_ONE = 10;
@Id
@GeneratedValue(generator = "possibleValuesID")
@GenericGenerator(name = "possibleValuesID", strategy = "increment")
@Column(name = "POSSIBLE_VALUES_ID")
private Long possibleValuesID;
@Transient
private SudokuPossibleValueState[] values = new SudokuPossibleValueState[NUMBER_OF_POSSIBLE_VALUES_PLUS_ONE];
// Ugly, disgusting hack, to deal with getting an Enumerated collection in/out of JPA/Hibernate
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState zero  = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState one   = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState two   = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState three = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState four  = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState five  = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState six   = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState seven = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState eight = SudokuPossibleValueState.UNDEFINED;
@Enumerated(EnumType.STRING)
private SudokuPossibleValueState nine  = SudokuPossibleValueState.UNDEFINED;
// Ugly, disgusting hack, to deal with getting an Enumerated array in/out of JPA/Hibernate
public PossibleValues() {
values[0] = zero;
values[1] = one;
values[2] = two;
values[3] = three;
values[4] = four;
values[5] = five;
values[6] = six;
values[7] = seven;
values[8] = eight;
values[9] = nine;
}
// Ugly, disgusting hack, to deal with getting an Enumerated array in/out of JPA/Hibernate
protected void setPossibleValue(short possibleValue, SudokuPossibleValueState state) {
switch (possibleValue) {
case 0: values[possibleValue] = zero = state; break;
case 1: values[possibleValue] = one = state; break;
case 2: values[possibleValue] = two = state; break;
case 3: values[possibleValue] = three = state; break;
case 4: values[possibleValue] = four = state; break;
case 5: values[possibleValue] = five = state; break;
case 6: values[possibleValue] = six = state; break;
case 7: values[possibleValue] = seven = state; break;
case 8: values[possibleValue] = eight = state; break;
case 9: values[possibleValue] = nine = state; break;
default: throw new RuntimeException("Possible Value [" + possibleValue + "] is illegal");
}
}
// Ugly, disgusting hack, to deal with getting an Enumerated array in/out of JPA/Hibernate
@PostLoad
protected void syncState() {
values[0] = zero;
values[1] = one;
values[2] = two;
values[3] = three;
values[4] = four;
values[5] = five;
values[6] = six;
values[7] = seven;
values[8] = eight;
values[9] = nine;
}
public Long getPossibleValuesID() {
return possibleValuesID;
}
@SuppressWarnings("unused")
private void setPossibleValuesID(Long possibleValuesID) {
this.possibleValuesID = possibleValuesID;
}
}

最新更新