JPA Enum ORDINAL vs STRING

问题描述 投票:38回答:8

可以使用其中任何一个在JPA中定义枚举

@Enumerated(EnumType.ORDINAL)

要么

@Enumerated(EnumType.STRING)

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

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

java orm jpa enums eclipselink
8个回答
65
投票

我总是去STRING

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

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

  1. 我可以改变我的枚举顺序
  2. 我可以在枚举列表的中间插入新的枚举

这两个更改都将改变数据库中已使用的枚举的序数值,因此如果使用ORDINAL则会破坏现有数据。

如果更改枚举值(不常见),处理它很简单:

UPDATE table SET enum_column = 'NEW_ENUM_NAME' where enum_column = 'OLD_ENUM_NAME';

16
投票

ORDINAL可能更有效率,但这是次要的。 ORDINAL有一些缺点:

  • 它在数据库中的可读性较差
  • 如果重新排序枚举定义,则数据库将不一致。

使用STRING,您无法重命名您的枚举。

选择其中一个并在整个应用程序中使用它 - 保持一致。

如果您的数据库将被其他客户端/语言使用 - 请使用STRING,它更具可读性。


3
投票

我更喜欢使用Ordinal但这实际上取决于使用。

举例:

你有一个enum,为了保存你的所有用户状态,在这种情况下顺序无关紧要,你可以在以后添加更多状态(最好用的是@Enumerated(EnumType.ORDINAL)):

public enum UserStates { ACTIVE, DELETED, PENDING }

但是现在,你有一个枚举,拯救太阳系中的行星(最好使用qazxsw poi):

@Enumerated(EnumType.STRING)

现在认为你想要重新排序你的行星,你不能使用public enum Planets {MERCURY,VENUS,EARTH,MARS,JUPITER,SATURN,URANUS,NEPTUNE,PLUTO,NINE} ,因为你的数据库无法知道你的Java文件中的新顺序。

您可以使用@Enumerated(EnumType.ORDINAL)重新排序您的Plantes,因为您的Planet与枚举名称相关联,而不是枚举顺序。

无论如何,您可以修改您的@Enumerated(EnumType.STRING)enums,因为它们与订单相关联,但您无法更改您的@Enumerated(EnumType.STRING)enums,因为它们将使用新的枚举。

字符串类型在数据库中更易读,但比有序数据的大小更多。如果数据库被更多客户使用,也许是有用的,但是最好有一个好的软件文档,而不是“EARTH”比“4”节省1000倍

@Enumerated(EnumType.STRING)

2
投票

这是一个很好的问题。在过去我使用String但今天我的偏好通常是Ordinal。

String的主要缺点是DBA。使用String,他们不知道列的可能值是什么,因为此信息位于应用程序代码中。 DBA只能对表中存在的信息分组的可能值有所了解,但他永远不会确定其他可能的值或是否添加了新值,直到应用程序将它们插入到表中。

在Ordinal你有同样的问题。但是我对Ordinal的偏好是DBA问题的解决方案,这对数据库来说似乎很自然。您创建一个新表以在数据库上显示Enumerator的可能值,并在列(序数枚举值)和此新表之间使用外键。这个策略被描述和实施USERSTATE ------------ ID | STATE | ------------ 1 | 1 2 | 2 3 | 1 Planets ------------ ID | Name | ------------ 1 | EARTH 2 | EARTH 3 | MARS 4 | EARTH

关于有人可以重新排序枚举器并破坏系统的问题,一个简单的单元测试可以解决这个问题,并保证没有好的警告就没人会重新排序。重命名Enumerator时,同样的想法是有效的。因此,意外地重命名(在String上)或重新排序(在Ordinal上)对于String或Ordinal方法来说并不是一个强有力的参数。

顺便说一句,开发人员更有必要重命名而不是重新排序枚举器,所以这是使用Ordinal的另一个积极点。

因此,通过这种方法,您可以解决Ordinal的主要问题(现在,可读),信息将占用数据库上较少的空间,您的DBA会很高兴。


0
投票

这取决于你的应用程序,如果你有更多机会使用String类型添加更多枚举,如果有更多的机会你将更改你的枚举名称使用Ordinal。


0
投票

这里有很多好建议,但我只想添加一些我还没看到的东西:

无论您选择何种解决方案,都不要忘记在枚举类的顶部添加一个大胖警告,说明应该使用哪个。希望其他开发人员会看到你已经完成了这个并使用相同的方法来保存枚举。


0
投票

我更喜欢EnumType.STRING。 EnumType.ORDINAL的缺点是时间的影响以及将枚举保持在逻辑顺序的愿望。使用EnumType.ORDINAL时,必须将任何新的枚举元素添加到列表的末尾,否则您将意外更改所有记录的含义。请检查此链接:here


-4
投票

您真的确定您需要的是人类可读的数据库吗?存储字符串值是浪费空间。可读性的唯一妥协可能是使用@Enumerated(STRING)和地图数据库列作为ENUM(如果你使用的是mysql ...我认为其他dbms有类似的东西)但是当你必须更改枚举名称时真的很痛苦。

© www.soinside.com 2019 - 2024. All rights reserved.