我有一个包含三个值的枚举。它被用作实体 bean 中的属性。
这是 bean 中的属性:
@Enumerated(EnumType.ORDINAL)
private BillingMethod billingMethod;
这是枚举类:
public enum BillingMethod {
ONLINEBILL("enum.billingmethod.onlinebill"), // Should be 1, but is now 0 in the database
PAPERBILL("enum.billingmethod.paperbill"), // Should be 2, but is now 1 in the database
PRINT("enum.billingmethod.print"); // Should be 3, but is now 2 in the database
private String tag;
private BillingMethod(String tag){
this.tag = tag;
}
@Override
public String getTag() {
return tag;
}
}
有一个非常罕见的具体原因,为什么我需要这些值为 1, 2, 3。而不是数据库中通常的 0, 1, 2。
不用担心这里的
tag
,它用于从属性文件中获取字符串表示。
那么,如何将 ORDINAL 设置为从 1 而不是 0 开始呢?
我看到两个选项:
最简单:为休眠映射一个整数,在 getter 中对枚举进行解码:
@Column(...)
private Integer billingMethod;
public BillingMethod getBillingMethod() {
// add here better error handling (logging additional info
// to help diagnose array out of bound exceptions).
return BillingMethod.values()[billingMethod - 1];
}
// add a setter doing a similar thing
问题是,如果不进行相同的编码/解码,则使用 hql 或条件搜索将无法工作。不太好。
创建自定义用户类型。更多信息请参阅参考文档
然后以这种方式映射该字段:
@Type("com.fully.qualified.class.name.of.MyUserType")
private BillingMethod billingMethod;
(当在
@Type
注释中使用用户类型的完全限定名称时,不需要注册)
实现起来有点复杂,但在标准枚举映射可以工作的所有情况下都可以工作
我们可以通过转换器实现它的另一种方法。
实体bean中的属性:
@Convert(converter = BillingMethodIdConverter.class)
private BillingMethod billingMethod;
枚举类:
public enum BillingMethod {
ONLINEBILL(1, "enum.billingmethod.onlinebill"),
PAPERBILL(2, "enum.billingmethod.paperbill"),
PRINT(3, "enum.billingmethod.print");
private static final Map<Integer, BillingMethod> mapById =
Stream.of(BillingMethod.values()).collect(toMap(t -> t.id, identity()));
public static BillingMethod fromId(Integer id) {
return Optional.ofNullable(mapById.get(id))
.orElseThrow(() -> new UnsupportedOperationException());
}
private final Integer id;
private final String tag;
private BillingMethod(Integer id, String tag) {
this.id = id;
this.tag = tag;
}
public Integer id() {
return id;
}
public String tag() {
return tag;
}
}
转换器:
@Converter
public class BillingMethodIdConverter implements AttributeConverter<BillingMethod, Integer> {
@Override
public Integer convertToDatabaseColumn(BillingMethod billingMethod) {
return billingMethod.id();
}
@Override
public BillingMethod convertToEntityAttribute(Integer id) {
return BillingMethod.fromId(id);
}
}
org.hibernate.usertype.UserType
接口的java文档中提到了这种方式。