可以使用
在JPA中定义枚举@Enumerated(EnumType.ORDINAL)
或
@Enumerated(EnumType.STRING)
我想知道这两个定义的优点和缺点是什么?
我听说ORDINAL比使用EclipseLink的STRING表现更好(更快) 这是真的吗?
答案 0 :(得分:64)
我总是去STRING
。
速度很少是最重要的问题 - 可读性和可维护性更重要。
我使用STRING
,因为手动检查数据库中的行要容易得多,但更重要的是,我可以做两件事,而不涉及数据库,ORDINAL
无法处理:< / p>
这两项更改都将改变数据库中已使用的枚举的序号值,因此如果您使用ORDINAL
,则会破坏现有数据。
如果更改枚举值(不常见),处理它很简单:
UPDATE table SET enum_column = 'NEW_ENUM_NAME' where enum_column = 'OLD_ENUM_NAME';
答案 1 :(得分:15)
ORDINAL
可能更有效率,但这是次要的。 ORDINAL
有一些缺点:
使用STRING
,您无法重命名您的枚举。
选择其中一个并在整个应用程序中使用它 - 保持一致。
如果您的数据库将由其他客户端/语言使用 - 请使用STRING
,它更具可读性。
答案 2 :(得分:3)
我更喜欢使用Ordinal
,但这真的取决于使用。
以示例:
您有一个枚举,要保存所有用户状态,在这种情况下订单无关紧要,您可以在以后添加更多状态(最佳用途为@Enumerated(EnumType.ORDINAL)
):
public enum UserStates { ACTIVE, DELETED, PENDING }
但是现在,你有一个枚举,用于保存太阳系中的种植体(最佳使用@Enumerated(EnumType.STRING)
):
public enum Planets {MERCURY,VENUS,EARTH,MARS,JUPITER,SATURN,URANUS,NEPTUNE,PLUTO,NINE}
现在认为你想要重新排序你的行星,你不能使用@Enumerated(EnumType.ORDINAL)
,因为你的数据库无法知道你的Java文件中的新顺序。
您可以使用@Enumerated(EnumType.STRING)
重新排序种植计划,因为您的星球链接到枚举名称,而不是枚举顺序。
无论如何,您可以修改@Enumerated(EnumType.STRING)
枚举,因为它们与订单相关联,但您无法更改@Enumerated(EnumType.STRING)
枚举,因为它们会使用新的枚举。
字符串类型在数据库中更具可读性,但其大小将超过有序数据。如果数据库被更多客户使用,也许是有用的,但是最好有一个好的软件文档,而不是“EARTH”比“4”节省1000倍
USERSTATE
------------
ID | STATE |
------------
1 | 1
2 | 2
3 | 1
Planets
------------
ID | Name |
------------
1 | EARTH
2 | EARTH
3 | MARS
4 | EARTH
答案 3 :(得分:2)
这是一个很好的问题。在过去我使用String但今天我的偏好通常是Ordinal。
String的主要缺点是DBA。使用String,他们不知道列的可能值是什么,因为此信息位于应用程序代码中。 DBA只能对表中存在的信息分组的可能值有所了解,但他永远不会确定其他可能的值或是否添加了新值,直到应用程序将它们插入到表中。
在Ordinal中你有同样的问题。但是我对Ordinal的偏好是DBA问题的解决方案,这对数据库来说似乎很自然。您创建一个新表以在数据库上显示Enumerator的可能值,并在列(序数枚举值)和此新表之间使用外键。该战略的描述和实施here。
关于有人可以重新排序Enumerator并破坏系统的问题,一个简单的单元测试可以解决这个问题,并保证没有好的警告就没人会重新排序。重命名Enumerator时,同样的想法是有效的。因此,意外地重命名(在String上)或重新排序(在Ordinal上)对于String或Ordinal方法来说并不是一个强有力的参数。
顺便说一句,开发人员更有必要重命名而不是重新排序Enumerator,所以这是使用Ordinal的另一个积极点。
因此,通过这种方法,您解决了Ordinal的主要问题(现在,可读),信息将占用数据库上更少的空间,并且您的DBA会很高兴。
答案 4 :(得分:0)
这取决于您的应用程序,如果您有更多机会使用String类型添加更多枚举,如果您更有可能更改枚举名称使用Ordinal。
答案 5 :(得分:0)
这里有很多好的建议,但我只想添加一些我尚未看到的内容:
无论选择哪种解决方案,都不要忘记在枚举类的顶部添加一个大的胖警告,指出应该使用哪种警告。希望其他开发人员可以看到您已经完成此操作,并使用相同的方法来保存枚举。
答案 6 :(得分:0)
我希望使用EnumType.STRING。 EnumType.ORDINAL的一个缺点是时间的影响以及保持枚举逻辑顺序的愿望。使用EnumType.ORDINAL必须将任何新的枚举元素添加到列表的末尾,否则您将不小心更改所有记录的含义。 请检查此链接: https://tomee.apache.org/examples-trunk/jpa-enumerated/
答案 7 :(得分:-4)
您真的确定您需要的是人类可读的数据库吗? 存储字符串值是浪费空间。可读性的唯一妥协可能是使用@Enumerated(STRING)和地图数据库列作为ENUM(如果你使用的是mysql ......我认为其他dbms有类似的东西)但是当你必须更改枚举名称时真的很痛苦。 / p>