我在这里看到了一些关于处理和持久化枚举类值(例如 适合枚举的持久化数据、 如何使用 NHibernate 持久化枚举)的最佳方法的问题/讨论,我想问一下大家的共识是什么。
特别是:
注意: 我把这个问题最初包含的解释移到了一个答案中。
至于代码部分:
你应该为你的枚举使用‘ enum’类型,基本上你会得到很多免费的东西,如果你这样做: 类型安全,封装和交换机避免,支持一些集合,如 EnumSet和 EnumMap和代码清晰度。
EnumSet
EnumMap
至于持久化部分,您总是可以持久化枚举的字符串表示形式,并使用枚举.valueOf (String)方法将其加载回来。
在数据库中存储枚举的文本值不如存储整数更可取,因为需要额外的空间和较慢的搜索速度。它的价值在于它比数字有更多的意义,然而数据库是用于存储的,而表示层是用于使事物看起来很漂亮。
Java 或 C # 应该总是在代码中使用枚举。免责声明: 我的背景是 C # 。
如果要将该值保存到数据库中,则应显式定义每个枚举成员的整数值,以便以后代码中的更改不会意外地改变已翻译的枚举值,从而改变应用程序行为。
值应该始终作为整数值保存到数据库中,以防止枚举名重构。在 wiki 中保存每个枚举的文档,并向数据库字段添加注释,指向记录类型的 wiki 页面。还要将 XML 文档添加到包含 wiki 条目链接的枚举类型,以便通过 Intellisense 获得它。
如果您使用一个工具来生成 CRUD 代码,那么它应该能够定义一个用于列的枚举类型,以便生成的代码对象始终使用枚举成员。
如果需要为枚举成员应用自定义逻辑,可以使用以下选项:
我还没有尝试过这种方法,但是在 SQL Server 2005或更高版本中,理论上可以将 C # 代码注册到包含枚举信息的数据库中,并且可以将值转换为枚举,以便在视图或其他构造中使用,这使得数据转换的方法更易于 DBA 使用。
在 C # 的代码处理中,你忽略了去关注0值的定义。 我总是毫无例外地声明我的第一个价值:
public enum SomeEnum { None = 0, }
以便作为一个空值。因为支持类型是一个整数,而整数默认为0,所以在很多地方知道枚举是否已经通过编程设置非常有用。
好吧,根据我的经验,对任何东西使用枚举,而不是将选项(作为标志)传递给一个直接的方法调用,在某些时候会导致 switch-ing。
switch
因此,对于一个具有更多功能的类似枚举的实体,您应该花一些时间并将其创建为一个类,要记住以下几点:
每次您发现自己在代码更改为枚举时使用“魔术数字”时。除了节省时间之外(因为当 bug 出现时魔法就会消失... ...) ,它还可以节省你的眼睛和内存(有意义的枚举可以使代码更具可读性和自编文档) ,因为你猜怎么着——你很可能是维护和开发自己的代码的人
最初的文章对我来说看起来很好。不过,基于这些评论,似乎有些关于 Java 枚举的评论可以澄清一些事情。
Java 中的 Enum 类型从定义上来说是一个类,但是许多程序员往往忘记了这一点,因为他们更愿意将其与其他一些语言中的“允许值列表”联系起来。不仅如此。
因此,为了避免这些 switch 语句,在枚举类中放置一些代码和其他方法可能是合理的。几乎没有必要创建一个单独的“类似枚举的实类”。
还要考虑文档的要点——是否要在数据库中记录枚举的实际含义?在反映值的源代码中(您的枚举类型)还是在某些外部文档中?我个人比较喜欢源代码。
如果由于速度或其他原因,希望将枚举值表示为数据库中的整数,那么该映射也应该驻留在 Java 枚举中。默认情况下,您将获得字符串名称映射,我对此很满意。每个枚举值都有一个序数,但是直接使用它作为代码和数据库之间的映射并不明智,因为如果有人对源代码中的值进行重新排序,那个序数就会改变。或者在现有值之间添加其他枚举值。或者失去一些价值。
(当然,如果有人更改了源代码中枚举的名称,默认的字符串映射也会失效,但这种情况不太可能意外发生。如果需要的话,可以通过在数据库中添加一些运行时检查和检查约束来更容易地防止这种情况的发生。)
我同意你所说的大部分内容。不过,关于枚举的持久性,我想补充一点: 我不认为在构建时从 DB 值生成枚举是可以接受的,但是我也认为运行时检查不是一个好的解决方案。我将定义第三种方法: 使用单元测试来检查枚举的值与数据库之间的关系。这可以防止“偶然”发散,并避免每次运行代码时根据数据库检查枚举的开销。
我知道这是一个老论坛,如果数据库可能有其他东西直接集成到它?例如,当结果数据库是代码的 SOLE 用途时。然后,您将在每次集成时定义枚举。总比把他们关在数据库里好。否则,我同意原来的帖子。
我试图总结我的理解。如果你有任何更正,请随意编辑这篇文章。所以这里是:
在密码里
在代码中,枚举应该使用语言的本机枚举类型(至少在 Java 和 C # 中)或者使用类似于 “类型安全枚举模式”的东西来处理。不建议使用普通常量(Integer 或类似的) ,因为这样会失去类型安全性(并且很难理解哪些值对于方法来说是合法输入)。
这两者之间的选择取决于枚举需要附加多少附加功能:
特别是,至少在 Java 中,一个枚举不能从另一个类继承,所以如果您有几个具有类似行为的枚举,并且您希望将它们放入一个超类中,那么您就不能使用 Java 的枚举。
持久枚举
为了持久化枚举,应该为每个枚举值分配一个唯一的 ID。这可以是一个整数,也可以是一个短字符串。短字符串是首选的,因为它可以是助记符(使 DBA 等更容易理解数据库中的原始数据)。
这种方法的一个问题是合法枚举值的列表存在于两个位置(代码和数据库)。这很难避免,因此往往被认为是可以接受的,但有两种选择: