- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
像往常一样,Java 枚举类型有相应的代码和名称描述。包含此类字段的 Java 类将它们包含为 Enum:
public enum MyEnum{
SOMEINSTANCE(1, "test1"),
SOMEINSTANCE(2, "test2");
private final int code;
private final String name;
private MyEnum(int code, String name){
this.code = code;
this.name = name;
}
... helper getter for code and name
}
@Entity
puclic class EnumHolder{
private MyEnum myEnum;
}
我是 JPA 的新手,但我希望拥有 'myEnums
' 表,如下所示:
code int not null, name varchar(50) not null)
在我的 enumHolder
表中,我希望有一个指向 myEnums 表的 myEnumCode
字段。
使用 currenlty 同时支持 EnumType.ORDINAL 和 EnumType.STRING 我想这不是一个好主意。
还有一个问题。如何使用 Java MyEnum
类数据填写 myEnums
表?你会怎么做?请最好的方法。
PS:我可以提供以下解决方案:
假设有一个表 myEnum
带有 code
和名称 fields
。问题中描述的 Java MyEnum
枚举。 enumHolder
表需要有 myEnumCode
对 myEnum.code
字段的引用。如果您不同意,请评论解决方案。
@Entity
@Access(AccessType.FIELD)
public class EnumHolder {
@Id private int id;
@Transient private MyEnum myEnum;
…
public int getId() { return id; }
public void setId(int id) { this.id = id; }
public MyEnum getMyEnum() { return MyEnum; }
public void setMyEnum(MyEnum myEnum) { this.myEnum = myEnum; }
@Access(AccessType.PROPERTY) @Column(name="myEnumCode")
protected int getMyEnumForDb() {
return myEnum.getCode();
}
protected void setMyEnumForDb(int enumCode) {
myEnum = MyEnum.getByCode( enumCode);
}
…
}
当然这里也有缺点。但目前我看不到更好的方法。请不要提供 EnumType.ORDINAL 和 EnumType.STRING 的替代品。我不想在这里写下它的使用可能存在的所有问题(在 Effective Java 中,它是关于序数用法的描述)。使用 EnumType.STRING 我不喜欢这两种方法,因为它不允许在数据库中有描述并从 db 请求它。
关于填充数据库。我认为编写一个脚本并不难,它清除 myEnum
表,然后为每个 Java 枚举实例插入表中。并且始终在部署阶段执行此操作。
最佳答案
最好的方法是将唯一的 ID 映射到每个枚举类型,从而避免 ORDINAL 和 STRING 的陷阱。看到这个post其中概述了映射枚举的 5 种方法。
取自以上链接:
1&2。使用@Enumerated
目前有 2 种方法可以使用 @Enumerated 注释在 JPA 实体中映射枚举。不幸的是,EnumType.STRING 和 EnumType.ORDINAL 都有其局限性。
如果您使用 EnumType.String,那么重命名您的枚举类型之一将导致您的枚举值与保存在数据库中的值不同步。如果您使用 EnumType.ORDINAL,则删除或重新排序枚举中的类型将导致保存在数据库中的值映射到错误的枚举类型。
这两个选项都很脆弱。如果枚举在未执行数据库迁移的情况下被修改,您可能会危及数据的完整性。
3.生命周期回调
一个可能的解决方案是使用 JPA 生命周期回调注解,@PrePersist 和 @PostLoad。这感觉非常难看,因为您的实体中现在将有两个变量。一个映射存储在数据库中的值,另一个映射实际的枚举。
4.将唯一 ID 映射到每个枚举类型
首选的解决方案是将您的枚举映射到枚举中定义的固定值或 ID。映射到预定义的固定值使您的代码更加健壮。对枚举类型顺序的任何修改,或者对名称的重构,都不会造成任何不利影响。
5.使用 Java EE7 @Convert
如果您使用的是 JPA 2.1,您可以选择使用新的 @Convert 注释。这需要创建一个使用@Converter 注释的转换器类,您可以在其中定义每种枚举类型将哪些值保存到数据库中。然后,在您的实体中,您将使用 @Convert 注释您的枚举。
我的偏好:(第 4 位)
我更喜欢在枚举中定义我的 ID 而不是使用转换器的原因是良好的封装。只有枚举类型应该知道它的 ID,只有实体应该知道它如何将枚举映射到数据库。
见原文post对于代码示例。
关于java - JPA 枚举类型映射。最佳方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16140282/
我是一名优秀的程序员,十分优秀!