如何使用Hibernate更新数据库模式而不丢失数据?

29

假设你正在使用Hibernate和JBoss开发Java EE应用程序。 你有一个运行中的服务器上存储着一些重要数据。 你每隔一段时间(1-2周)发布一次应用程序的下一个版本,并在持久层中进行一堆更改:

  • 新增实体
  • 删除实体
  • 属性类型更改
  • 属性名称更改
  • 关联关系更改

如何有效地设置一个系统来更新数据库架构并保留数据? 据我所知(我可能错了),Hibernate不执行alter column、drop/alter constraint等操作。

谢谢, Artem B.

7个回答

17

LiquiBase是您的最佳选择。它有一个Hibernate集成模式,使用Hibernate的hbm2ddl来比较数据库和Hibernate映射,但不会自动更新数据库,而是输出一个Liquibase变更记录文件,可在实际运行前进行检查。

虽然更方便,但任何对数据库和Hibernate映射进行比较的工具都可能出现错误。请参见http://www.liquibase.org/2007/06/the-problem-with-database-diffs.html以获取示例。使用Liquibase,您可以建立一个数据库更改列表,以便在开发过程中,格式能够在代码分支和合并时生存。


参见:http://dobesland.wordpress.com/2008/01/08/database-schema-migration/#comment-249 - Hendy Irawan

4

我个人会跟踪迁移SQL脚本中的所有更改。


1
在您需要在不同的时间部署到不同的机器上时,我不建议这样做。 - Hola Soy Edu Feliz Navidad

4
你可以使用https://github.com/Devskiller/jpa2ddl工具,该工具提供Maven和Gradle插件,并能够基于JPA实体生成自动模式迁移,以用于Flyway。它还包括所有属性、方言、用户类型、命名策略等。

我还推荐使用Flyway来保持不同环境之间所有数据库的同步。例如,如果另一个开发人员添加了一列,下次我拉取并启动服务器时,Flyway会在我的本地数据库上运行SQL以添加该列。在部署到测试环境或生产环境时也是如此。 - xtian

2
作为对Nathan Voxland关于LiquiBase所说的进一步回应,以下是在Windows下执行针对mySql数据库的迁移的示例:
将mysql连接器放置在Liquibase分发包的lib文件夹下。
在Liquibase分发包的根目录中创建一个名为liquibase.properties的属性文件,并插入以下经常使用的行:
driver: com.mysql.jdbc.Driver
classpath: lib\\mysql-connector-java-5.1.30.jar
url: jdbc:mysql://localhost:3306/OLDdatabase
username: root
password: pwd

生成或检索更新的数据库,并使用另一个名称,例如NEWdatabase
现在,您将使用以下命令行从文件Migration.xml中提取差异:
liquibase diffChangeLog --referenceUrl="jdbc:mysql://localhost:3306/NEWdatabase" 
--referenceUsername=root --referencePassword=pwd > C:\Users\ME\Desktop\Migration.xml

最后,使用刚生成的 Migration.xml 文件执行更新操作:
java -jar liquibase.jar --changeLogFile="C:\Users\ME\Desktop\Migration.xml" update

注意:所有这些命令行应该从Liquibase主目录执行,其中包含liquibase.bat/.sh和liquibase.jar。

2

我使用了Hibernate内置的SchemaUpdate来处理一个应用程序,直接在引导类中使用,这样每次启动应用程序时都会检查模式。这可以处理添加新列或表的情况,这通常是成熟应用程序中发生的事情。为了处理特殊情况,例如删除列,引导程序只需手动在try/catch中运行ddl,因此如果已经删除一次,它只会静默地抛出错误。我不确定在生产应用程序中处理关键数据是否适用,但在几年和数百次部署中,我从未遇到过问题。


1

你也可以使用DBMigrate。它类似于Liquibase:

这个库与Ruby on Rails的'rake migrate'类似,它允许你管理Java应用程序的数据库升级。


1
我使用hbm2ddl ant任务来生成我的ddl。有一个选项可以在数据库中执行alter tables/columns。
请查看hbm2ddl ant任务的"update"属性。

http://www.hibernate.org/hib_docs/tools/reference/en/html/ant.html#d0e1137

update(默认值:false):尝试创建一个更新脚本,表示数据库中的内容与映射之间的“增量差异”。忽略创建/更新属性。(不要用于生产数据库,无法保证可以生成正确的增量或底层数据库能够执行所需的操作)

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