是否可以运行配置了hbm2ddl的Hibernate应用程序。自动=update在生产环境中更新数据库模式?


当前回答

我会投反对票。当列的数据类型发生变化时,Hibernate似乎无法理解。示例(使用MySQL):

String with @Column(length=50)  ==> varchar(50)
changed to
String with @Column(length=100) ==> still varchar(50), not changed to varchar(100)

@Temporal(TemporalType.TIMESTAMP,TIME,DATE) will not update the DB columns if changed

可能还有其他的例子,比如将String列的长度提高到255以上,然后看到它转换为文本、mediumtext等等。

当然,我不认为真的有一种方法可以在不创建新列、复制数据和删除旧列的情况下“转换数据类型”。但是一旦你的数据库中有不能反映当前Hibernate映射的列,你就非常危险了……

Flyway是解决这个问题的一个很好的选择:

http://flywaydb.org

其他回答

这不安全,也不推荐,但这是可能的。

我有在生产环境中使用自动更新选项的应用程序的经验。

在这个解决方案中发现的主要问题和风险是:

Deploy in the wrong database. If you commit the mistake to run the application server with a old version of the application (EAR/WAR/etc) in the wrong database... You will have a lot of new columns, tables, foreign keys and errors. The same problem can occur with a simple mistake in the datasource file, (copy/paste file and forgot to change the database). In resume, the situation can be a disaster in your database. Application server takes too long to start. This occur because the Hibernate try to find all created tables/columns/etc every time you start the application. He needs to know what (table, column, etc) needs to be created. This problem will only gets worse as the database tables grows up. Database tools it's almost impossible to use. To create database DDL or DML scripts to run with a new version, you need to think about what will be created by the auto-update after you start the application server. Per example, If you need to fill a new column with some data, you need to start the application server, wait to Hibernate crete the new column and run the SQL script only after that. As can you see, database migration tools (like Flyway, Liquibase, etc) it's almost impossible to use with auto-update enabled. Database changes is not centralized. With the possibility of the Hibernate create tables and everything else, it's hard to watch the changes on database in each version of the application, because most of them are made automatically. Encourages garbage on database. Because of the "easy" use of auto-update, there is a chance your team neglecting to drop old columns and old tables, because the hibernate auto-update can't do that. Imminent disaster. The imminent risk of some disaster to occur in production (like some people mentioned in other answers). Even with an application running and being updated for years, I don't think it's a safe choice. I never felt safe with this option being used.

因此,我不建议在生产环境中使用自动更新。

如果你真的想在生产环境中使用自动更新,我建议:

网络分开。您的测试环境无法访问同源环境。这有助于防止原本应该在测试环境中的部署更改同源数据库。 管理脚本顺序。您需要在部署之前(结构表更改、删除表/列)和部署之后(填充新列/表的信息)组织运行的脚本。

而且,与其他文章不同的是,我不认为自动更新启用了它与“高薪”dba有关(如其他文章所述)。dba有比编写SQL语句来创建/更改/删除表和列更重要的事情要做。这些简单的日常任务可以由开发人员完成和自动化,只需要DBA团队进行检查,而不需要Hibernate和DBA“高薪”编写它们。

我不会冒这个险,因为你可能会丢失本该保存的数据。hbm2ddl。Auto =update纯粹是一种保持开发数据库最新的简单方法。

应用程序的模式可能会随着时间而变化;如果您有多个安装,可能是不同的版本,您应该有某种方法来确保您的应用程序、某种工具或脚本能够逐步将模式和数据从一个版本迁移到下一个版本。

将所有持久性放在Hibernate映射(或注释)中是控制模式演变的一种非常好的方法。

您应该考虑模式演化有几个方面需要考虑:

数据库模式的演变 添加更多的列和表 删除旧的列,表和 关系 用默认值填充新列

Hibernate工具非常重要,特别是当你在许多不同类型的数据库上有相同应用程序的不同版本时(就像我的经验一样)。

第3点在使用Hibernate时非常敏感,例如在引入一个新的布尔值属性或数值属性时,如果Hibernate在这些列中发现任何空值,则会引发异常。

所以我要做的是:确实使用Hibernate工具的模式更新功能,但必须在它旁边添加一些数据和模式维护回调,比如填充默认值,删除不再使用的列,等等。通过这种方式,您获得了优势(独立于数据库的模式更新脚本和避免在持久性和脚本中对更新进行重复编码),但也涵盖了操作的所有方面。

因此,例如,如果版本更新只是添加一个varchar值属性(即列),它可能默认为null,那么使用自动更新就可以完成。在需要更复杂的地方,就需要做更多的工作。

这是假设更新时的应用程序能够更新其模式(这是可以做到的),这也意味着它必须拥有对模式进行更新的用户权限。如果客户的策略阻止了这一点(可能是Lizard Brain的情况),您将不得不提供特定于数据库的脚本。

在我的情况下(Hibernate 3.5.2, Postgresql, Ubuntu),设置Hibernate .hbm2ddl。Auto =update仅创建新表,并在已有的表中创建新列。 它既不删除表,也不删除列,也不更改列。它可以被称为一个安全的选择,但有点像hibernate.hbm2ddl。Auto =create_tables add_columns更清楚。

不,永远不要这么做。Hibernate不处理数据迁移。是的,它将使您的模式看起来正确,但它不能确保有价值的生产数据不会在过程中丢失。