JPA Enum ORDINAL vs STRING

时间:2011-07-22 11:32:06

标签: java orm jpa enums eclipselink

可以使用

在JPA中定义枚举
@Enumerated(EnumType.ORDINAL)

@Enumerated(EnumType.STRING)

我想知道这两个定义的优点和缺点是什么?

我听说ORDINAL比使用EclipseLink的STRING表现更好(更快) 这是真的吗?

8 个答案:

答案 0 :(得分:64)

我总是去STRING

速度很少是最重要的问题 - 可读性和可维护性更重要

我使用STRING,因为手动检查数据库中的行要容易得多,但更重要的是,我可以做两件事,而不涉及数据库,ORDINAL无法处理:< / p>

  1. 我可以更改枚举的顺序
  2. 我可以在枚举列表中间插入新的枚举
  3. 这两项更改都将改变数据库中已使用的枚举的序号值,因此如果您使用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>