我正在尝试使用Sparx Enterprise Architect来设计最终将存储在MySQL数据库中的数据模型。
我的第一种方法是Data Model diagram,可用于generate DDL(或reverse engineering的其他方式)。
这很有效,但是一位同事指出了一个障碍:我们打算使用ORM(几乎可以肯定是Hibernate)将表映射到Java类。他的评论是“数据库优先”方法,将排除使用良好的OO技术,如继承。
这似乎是一个好点,但我想知道是否有任何限制。如果我从头开始使用Class Diagram而不是数据模型图,那么是否可以在此模型中包含所有必需的Hibernate注释,配置等?如果我后来需要建模特定于数据库的功能,例如约束,触发器等,那么在模型中,所有这些都是可能的,因为类图并不真正针对这类事物吗?
答案 0 :(得分:8)
让我回答一个问题:如果你想建造一所房子,你会先建造它然后再打印出来,或者你会先制定计划吗? :)
软件开发就是逐渐降低抽象。我们从一个非常抽象的项目想法开始,然后做一些reqs(显然有点不那么抽象),然后架构,设计和完美地进入编码层面(最低抽象)
数据模型是可能最低抽象级别的模型(可直接映射到DDL),所以这是你要做的最后一件事。
域类模型是数据库的更高抽象。它甚至是Hibernate层的抽象,因为它也在抽象的实现层面上。
所以,我首先要使用OO的类和全部功能来定义域的模型。尝试使实现独立的类模型。不要假设JAVA,Hibernate,DB,任何东西,而是专注于您的域逻辑。做一种" utopic"域模型,逻辑上完美结构的域类。
然后使用相应的转换从此模型派生Hibernate层和DB本身。
答案 1 :(得分:7)
I prefer to model the database first。数据库是业务中最有价值的部分,应用程序逻辑只是操作业务数据的接口。
由于数据库往往比应用程序技术更长,因此最好先设计它,因为设计通常由数据关系和数据查询模型驱动。
大多数ORM旨在将域对象建模为现有模式,它是ORM工具任务,以应对任何可能的db模式映射conecer。
对于快速原型设计,我可能会考虑从域对象生成模式,但在设计大型企业系统体系结构时,这种方法是次优的。
Hibernate仅提供有限数量的DDL功能,我不想放弃额外的数据库特定功能,如PosgreSQL domains,instead-of triggers,materialized views或MySQL triggers
像Flyway这样的工具最适合用于自动化架构迁移过程。
答案 2 :(得分:5)
无论您使用哪种技术,都应始终“最重要的事实” 。 XML接口的真相在哪里?在其XSD规范中,没有某些使用任意语言的实现类。同样,与RDBMS交互时的真实情况在哪里?它在数据库中,以DDL形式编写。数据库应“拥有”其架构,而不是从某些派生的客户端表示中生成数据库。 I've written about this topic here。
这是保持对数据库重要的语言来控制数据库模式的唯一合理方法。这也是合理的唯一方法:
我们打算使用ORM(几乎可以肯定是Hibernate)将表映射到Java类。他的评论是“数据库优先”的方法将排除使用继承等良好的面向对象技术。
首先应该问自己为什么需要继承。由于您是使用关系模型存储数据的,因此您应该使用关系模型的建模功能,并且所有客户端表示形式(例如,您的ORM)都应从中得出。在极少数情况下,继承甚至是该领域中可行的建模技术,并且大多数情况下仍然不能很好地工作,因为在OO进行了20多年之后,人们得出结论,继承在OO的早期就被过度使用-特别是继承数据结构。构图应该受到青睐,并且无论如何应该更具关系。
您的关系模型有可能超过OO客户表示,并且应该确保关系模型是正确的和规范化的,等等。
这似乎是个好主意,但我想知道是否有任何限制。如果我从头开始使用类图而不是数据模型图,是否可以在该模型中包含所有必需的Hibernate批注,配置等?而且,如果以后我需要对特定于数据库的功能(例如约束,触发器等)进行建模,考虑到“类图”并非真正针对此类事物,那么在模型中是否可以实现所有这些功能?
我认为您不需要通过派生的类图浏览数据库模型。考虑您的ERD(可以从DDL生成)。 ORM的表示将简单地反映出这一点。
答案 3 :(得分:2)
这是域驱动设计的一票,首先是类/代码。
首先创建hibernate实体类,这就是你要编写的代码 - 把它们弄好,为什么要关心什么是持久的 - 因为你不打算编写sql(?)。我的进程是创建类,如果你需要的话,从它们中吐出uml(尽管很少有资源),让hibernate构建db。
我尝试避免供应商特定的数据库功能 - 根据定义它会有点奇怪。
答案 4 :(得分:2)
领域模型首先,永远和永远。 然后DB和实体同时进行。