Hibernate/JPA数据库模式生成的最佳实践

48

我想听一下Hibernate专家关于基于Hibernate/JPA的项目中最佳DB架构生成实践的意见。尤其是:

  1. 在项目刚开始时使用什么策略?这个阶段推荐让Hibernate自动生成架构,还是更好地从项目的早期手动创建数据库表格?

  2. 假设整个项目都是使用Hibernate生成架构,是禁用自动架构生成并在系统发布到生产之前手动创建数据库架构更好呢?

  3. 在系统发布到生产后,如何最好地维护实体类和DB架构(例如添加/重命名/更新列,重命名表等)?


我猜这样一个大问题很大程度上取决于你的项目以及它所能接受的内容:
  • 中央部署(例如基于JEE)与客户端-服务器模式之间的选择
  • 允许任何时候使用多个客户端版本(=>注意数据库列删除、完整性约束等)
  • 热部署与停止应用程序之间的接受程度
  • ...
- Matthieu BROUILLARD
6个回答

40
  1. 建议手动生成数据库模式,最好使用支持数据库模式修订的工具(如优秀的Liquibase)。虽然从实体中生成模式在理论上很棒,但在实践中易受损,并在长期运行中导致许多问题(相信我)。

  2. 在生产环境中,最好手动生成并检查模式。

  3. 当对实体进行更新时,请创建一个匹配的更新脚本(修订),以更新数据库模式以反映实体变更。您可以创建自定义解决方案(我写过几个),或使用像Liquibase这样更流行的工具(它甚至支持模式更改回滚)。如果您正在使用构建工具(如Maven或Ant),建议将数据库模式更新工具插入构建过程中,以便新构建与模式保持同步。


你能具体说明在长期内可能出现哪些问题,特别是在生产方面吗?这将非常有用。 - Migi

14

虽然有争议,但我认为对于所有3个问题的答案都是:让hibernate自动在模式中生成表。

到目前为止,我没有遇到任何问题。您可能需要定期手动清理一些字段,但这与单独跟踪DDL脚本(即管理其修订版本并将其与实体更改同步 - 反之亦然)相比不麻烦。

对于部署到生产环境的提示-一个明显的提示-首先确保在测试环境上一切都正常生成,然后再部署到生产环境。


1
但是假设您必须在生产环境中更改实体关系,以一种会导致创建新表的方式,因此,曾经属于旧表一部分的某些数据必须插入到这些新表中。例如,假设您有一个名为Person的实体,其中包含地址信息字段,现在您想创建一个单独的实体来保存地址信息。这将导致创建一个新表,并且您必须将地址数据从person表迁移到这个新表中。但是Hibernate无法自动执行此操作... - Behrang
5
就个人而言,我强烈反对采用这种方法,特别是在谈论生产时。对我来说,这个过程的控制不够,而且涉及了太多的“魔法”。 - rudolfson
2
Liquibase可以为您解决“分别跟踪DDL脚本 - 即管理其修订版本并将其与实体更改(反之亦然)同步”的所有问题。您可以清楚地了解到应用了哪些数据库方案更改。使用自动生成表格,您根本不需要任何版本控制。有些更改可能会影响您的数据,导致数据丢失。这对于生产环境来说完全不安全,只适用于开发环境。 - Alexandr

8

手动操作,因为:

  1. 同一数据库可能被不同的应用程序使用,且并非所有应用程序都使用Hibernate甚至Java。数据库架构不应由ORM指定,而应围绕数据和业务需求进行设计。
  2. Hibernate选择的数据类型可能不适合于应用程序。
  3. 如早期评论中所述,如果不能接受数据丢失,则对实体的更改需要手动干预。
  4. 在RDBMS上,加入表上的附加属性(通用术语而非Java属性)等内容可正常工作,但在ORM中使用这些内容会有些复杂和低效。从ORM -> RDBMS做这样的映射可能会创建不高效的表。理论上,可以使用Hibernate生成的代码构建完全相同的联接表,但在编写实体时需要特别注意。

我会在独立应用程序或通过相同ORM层访问的数据库中使用自动生成。如果应用程序需要移植到不同的数据库,则可以节省大量时间,因为无需编写和维护特定于DB供应商的DDL脚本。


1
如果您有不同的应用程序使用同一数据库,最好的做法是为数据库交互使用一个共同的API,这个API被不同应用程序使用。更好的方式是使用一个 Web 服务作为您与数据库的接口。Web 服务更好,因为它是独立于编程语言的。通过此方式——无论是使用 API 还是 Web 服务——您都可以将数据库集中到一个单一的点上,从而使得数据库版本控制和数据定义语言更改变得更容易。这个单一的点还可以创建和更新数据库。 - Cengiz

5

就像Bozhidar所说的那样,不要让Hibernate创建和更新数据库架构。 让你的应用程序创建和更新数据库架构。 对于Java来说,最好的工具是Flyway。您需要创建一个或多个包含DDL语句的SQL文件,这些语句描述了您的数据库架构。然后,Flyway会执行这些SQL文件。有关更多信息,请查看Flyway网站。


1
Flyway需要手动创建一个SQL文件来完成这个任务,它不能“让你的应用程序创建和更新数据库模式”。 - Bằng Rikimaru
@Bang:Flyway和它的SQL文件是应用程序的一部分。因此,可以说该应用程序正在创建数据库模式。 - Cengiz
你的评论被误解了,因为你说“不要让Hibernate创建和更新数据库模式”,所以有些人认为,好吧,Hibernate不适合做这个,那就没事了。“让你的应用程序创建和更新数据库模式。对于Java来说,最好的工具是Flyway。”所以Flyway是为应用程序创建和更新数据库模式的最佳工具,太棒了,然后他查看了Flywaydb的网站,并感到失望,因为它需要一个Sql文件。 - Bằng Rikimaru

3
我相信这里讨论或争论的很多内容也应该与您更喜欢的代码优先还是数据库优先方法相关。就个人而言,我更倾向于后者,并且参考单一职责原则(SRP),我更喜欢由数据库专家处理数据库,由应用程序专家处理应用程序,而不是应用程序处理数据库。此外,我认为在开始时采取太多捷径可能会很好,但随着事物的增长/发展,会产生无法管理的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接