【发布时间】:2015-10-02 10:58:43
【问题描述】:
我的数据库架构中有一个表,其中包含我正在构建的应用程序的配置信息。我想根据表的内容生成一些枚举。我目前在我的构建脚本中使用 JOOQ 从同一个数据库生成其他标准 JOOQ 类,并希望我可以通过 JOOQ 获得这个新功能。
例如,如果表包含以下数据
Product Component PresentationOrder
HydroProduct Boat 1
HydroProduct Canoe 2
HyrdoProduct Ship 3
LandProduct Car 1
LandProduct Bike 2
然后我想生成两个枚举
hydroProduct.Components { Boat, Canoe, Ship; }
和
landProduct.Components {Car, Bike; }
其中hydroProduct 和landProduct 是包,枚举都称为组件。
确切的细节有待商榷(例如,我可以使用不同的命名约定,因此欢迎提出任何建议),但原则(一个表中的两个枚举,基于其中的数据)至少是对于这个问题,我需要的东西。
阅读了 JOOQ 文档后,我发现生成枚举曾经是 JOOQ 的一部分,然后被删除了。我看不到在 JOOQ 中做我想做的事情的“明显”方式,但它是一个非常了不起的库,所以我猜可能会有一个。
编辑
许多评论者对整体方法提出了质疑,我理解这一点。我想避免这种对话——我基本上不可能在这个论坛上讨论这种设计水平。这种方法(基于 DDL 和 SQL 的代码生成)在我的组织中经过了很好的测试,并且经过了大量的设计审查。
只是为了记录,这里是管道的轮廓。我把它放进去是因为我很感激人们花时间考虑我最初的问题,我想说明这个问题如何适合我们的整体开发系统。
Project One 包含一些引导类、一些 DDL 和一些 SQL 脚本,其中包含我们整个系统使用的数据常量。它的输出包括(以及其他内容),一些 .jar 文件,其中包含生成的类的编译版本。这些基本上构成了我们系统其余部分用来交流的核心商定词汇。
项目二拥有java源代码,它利用了项目一生成的各种人工制品。在项目二被编译之前,可以假设项目一的人工制品已经生成。因此,例如,从项目 1 中保存的数据生成的 Enum 可以在编译时用于项目 2。
我们的构建脚本构建项目一,并使输出可用于项目二。这包括生成 Eclipse 项目文件,以便项目 2 的用户可以为项目的任何分支签出、构建和打开 Eclipse,并且它“正常工作”。
还有其他项目(包括不同的语言,例如 Javascript)也使用项目一生成的人工制品。
这种方法的主要好处是,当项目一中的数据发生变化时,项目一中的类和枚举的定义因此发生变化,项目二会通过编译时错误而不是运行时错误来反映这种变化.这在实践中的好处绝对是巨大的。是的,有一个设置成本,但在我们的经验中,像 JOOQ(我们用来生成项目 1 的输出)这样的工具使我们比以前更有效率。
在我们发布桌面、浏览器内和 J2EE 组件并且它们都需要一起交流的情况下尤其如此。
【问题讨论】:
-
enums 应该是编译时常量,因此根据数据库中的数据生成它们是 IMO 有问题的;如果有人在您发布软件后插入新值或删除现有值怎么办? -
@Mick:在某些时候,必须决定规范常量的定义位置。 DDL 与 Java 文件一样是我的源代码的一部分。由于我已经从 DB 中生成了一堆 Java 类,然后进行了编译,因此数据库位于我的 Java 源代码的“上游”——所以我在数据库中定义了这些常量。如果有人在数据库中添加或删除现有行,则数据库和代码不再兼容。如果有人向源中的枚举添加一个常量,这也是正确的。
-
我可以理解 DDL 是“源的一部分”,因为它描述了表的 结构。但是,我认为实际的 data 应该区别对待;如果给定表中的数据不应该在您的软件版本之间发生变化,那么当您可以将其存储在属性文件中时,为什么还要将其保存在数据库中?
-
你的观点是完全正确的。我做出了我做出的选择,因为我判断 (a) 数据库和 Java 源代码必须就一组常量达成一致,(b) 编码该协议的最佳方法是将它们编码为数据库中的数据和枚举在 Java 中,(c) 数据库是我所知道的管理数据的最佳工具。有了这三个假设(它们只是我的假设),最好的做法是使用数据库来定义常量,并在 Java 中派生枚举。添加第三个位置来定义常量(如属性文件)对我来说吸引力不大。
-
@MickMnemonic:这当然有助于区分“普通数据”和“主数据”,后者更接近于元数据 (DDL) 而不是用户数据。当然,这是一条细线,但假设主数据很少更改,就像 DDL...