【问题标题】:How to update a database schema without losing your data with Hibernate?如何使用 Hibernate 在不丢失数据的情况下更新数据库模式?
【发布时间】:2010-10-18 18:55:52
【问题描述】:

假设您正在使用 Hibernate 和 JBoss 开发 Java EE 应用程序。您有一个正在运行的服务器,上面有一些重要数据。您偶尔(1-2 周)发布应用程序的下一个版本,并且它们在持久层中发生了很多变化:

  • 新实体
  • 删除的实体
  • 属性类型更改
  • 属性名称更改
  • 关系变化

您如何有效地建立一个更新数据库架构并保留数据的系统?据我所知(我可能弄错了),Hibernate 不执行更改列、删除/更改约束。

谢谢你, Artem B.

【问题讨论】:

    标签: database hibernate schema migrate


    【解决方案1】:

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

    【讨论】:

    • 当您必须在不同时间部署在不同机器上时,我不建议您这样做。
    【解决方案2】:

    【讨论】:

      【解决方案3】:

      我使用 hbm2ddl ant 任务来生成我的 ddl。有一个选项可以在您的数据库中执行更改表/列。

      请看 hbm2ddl 蚂蚁任务的“更新”属性:

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

      update(default: false): 尝试创建 一个更新脚本,代表 之间的“增量” 数据库和什么映射 指定。忽略创建/更新 属性。 (不要使用反对 生产数据库,不保证 正确的增量可以是所有 生成也不是底层 数据库实际上可以执行 需要的操作)

      【讨论】:

        【解决方案4】:

        对于一个应用程序,我使用 SchemaUpdate,它内置于 Hibernate,直接来自引导程序类,因此每次应用程序启动时都会检查架构。这负责添加新的列或表,这主要发生在成熟的应用程序上。为了处理特殊情况,比如删除列,引导程序只是在 try/catch 中手动运行 ddl,所以如果它已经被删除一次,它只会默默地抛出一个错误。我不确定我是否会在生产应用程序中处理关键任务数据,但在几年和数百次部署中,我从未遇到过问题。

        【讨论】:

          【解决方案5】:

          LiquiBase 是您最好的选择。它有一个hibernate integration 模式,它使用 Hibernate 的 hbm2ddl 来比较您的数据库和您的 hibernate 映射,但它不会自动更新数据库,而是输出一个 liquibase 更改日志文件,可以在实际运行之前对其进行检查。

          虽然更方便,但任何比较数据库和休眠映射的工具都会出错。有关示例,请参阅http://www.liquibase.org/2007/06/the-problem-with-database-diffs.html。使用 liquibase,您可以在开发时建立一个数据库更改列表,该格式可以在带有分支和合并的代码中幸存下来。

          【解决方案6】:

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

          类似于 Ruby on 的“rake migrate” Rails 这个库让你管理 Java 的数据库升级 应用程序。

          【讨论】:

            【解决方案7】:

            作为对 Nathan Voxland 关于LiquiBase 的进一步回应,下面是一个在 Windows 下为 mySql 数据库执行迁移的示例:

            例如,将 mysql connector 放在 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.bat/.sh 和 liquibase.jar 所在的 liquibase 主目录执行。

            【讨论】:

              【解决方案8】:

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

              【讨论】:

              • 我还推荐 Flyway 作为在不同环境之间保持所有数据库同步的一种方式。例如,如果另一个开发人员添加了一个列,下次我拉动并启动服务器时 Flyway 运行 sql 以将该列添加到我的本地数据库中。部署到测试环境或生产环境时也是如此。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-01-25
              • 1970-01-01
              • 2019-06-04
              • 2017-02-17
              • 2011-08-10
              • 2016-08-21
              • 2015-07-03
              相关资源
              最近更新 更多