database 如何使用 Hibernate 在不丢失数据的情况下更新数据库模式?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/737989/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 07:14:53  来源:igfitidea点击:

How to update a database schema without losing your data with Hibernate?

databasehibernateschemamigrate

提问by artemb

Imagine you are developing a Java EE app using Hibernate and JBoss. You have a running server that has some important data on it. You release the next version of the app once in a while (1-2 weeks) and they have a bunch of changes in the persistence layer:

假设您正在使用 Hibernate 和 JBoss 开发 Java EE 应用程序。您有一个正在运行的服务器,上面有一些重要的数据。您不时发布应用程序的下一个版本(1-2 周),它们在持久层中有一系列更改:

  • New entities
  • Removed entities
  • Attribute type changes
  • Attribute name changes
  • Relationship changes
  • 新实体
  • 删除的实体
  • 属性类型更改
  • 属性名称更改
  • 关系变化

How do you effectively set up a system that updates the database schema and preserves the data? As far as I know (I may be mistaking), Hibernate doesn't perform alter column, drop/alter constraint.

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

Thank you, Artem B.

谢谢你,阿尔乔姆 B。

采纳答案by Nathan Voxland

LiquiBaseis your best bet. It has a hibernate integrationmode that uses Hibernate's hbm2ddl to compare your database and your hibernate mapping, but rather than updating the database automatically, it outputs a liquibase changelog file which can be inspected before actually running.

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

While more convenient, any tool that does a comparison of your database and your hibernate mappings is going to make mistakes. See http://www.liquibase.org/2007/06/the-problem-with-database-diffs.htmlfor examples. With liquibase you build up a list of database changes as you develop in a format that can survive code with branches and merges.

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

回答by Jakub Kubrynski

You can use https://github.com/Devskiller/jpa2ddltool which provides Maven and Gradle plugin and is capable of generating automated schema migrations for Flywaybased on JPA entities. It also includes all properties, dialects, user-types, naming strategies, etc.

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

回答by Maurice Perry

I personally keep track of all changes in a migration SQL script.

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

回答by Brian Deterling

For one app I use SchemaUpdate, which is built in to Hibernate, straight from a bootstrap class so the schema is checked every time the app starts up. That takes care of adding new columns or tables which is mostly what happens to a mature app. To handle special cases, like dropping columns, the bootstrap just manually runs the ddl in a try/catch so if it's already been dropped once, it just silently throws an error. I'm not sure I'd do this with mission critical data in a production app, but in several years and hundreds of deployments, I've never had a problem with it.

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

回答by Jad B.

As a further response of what Nathan Voxland said about LiquiBase, here's an example to execute the migration under Windows for a mySql database:

作为对 Nathan Voxland 所说的LiquiBase的进一步回应,这里有一个在 Windows 下为 mySql 数据库执行迁移的示例:

Put the the mysql connectorunder libfolder in liquibase distribution for example.

例如,将 mysql连接器放在 liquibase 发行版中的lib文件夹下。

Create a file properties liquibase.propertiesin the root of the liquibase distribution and insert this recurrent lines :

在 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

Generate or retrieve an updated database under another name for example NEWdatabase.

以另一个名称生成或检索更新的数据库,例如NEWdatabase

Now you will exctract differences in a file Migration.xmlwith the following command line :

现在,您将使用以下命令行提取文件Migration.xml 中的差异:

liquibase diffChangeLog --referenceUrl="jdbc:mysql://localhost:3306/NEWdatabase" 
--referenceUsername=root --referencePassword=pwd > C:\Users\ME\Desktop\Migration.xml

Finally execute the update by using the just generated Migration.xmlfile :

最后使用刚刚生成的Migration.xml文件执行更新:

java -jar liquibase.jar --changeLogFile="C:\Users\ME\Desktop\Migration.xml" update

NB: All this command lines should be executed from the liquibase home directory where liquibase.bat/.sh and liquibase.jar are present.

注意:所有这些命令行都应该从 liquibase.bat/.sh 和 liquibase.jar 所在的 liquibase 主目录中执行。

回答by Hendy Irawan

You can also use DBMigrate. It's similar to Liquibase :

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

Similar to 'rake migrate' for Ruby on Rails this library lets you manage database upgrades for your Java applications.

类似于 Ruby on Rails 的 'rake migrate',这个库让您可以管理 Java 应用程序的数据库升级。

回答by Matt Sidesinger

I use the hbm2ddl ant task to generate my ddl. There is an option that will perform alter tables/columns in your database.

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

Please see the "update" attribute of the hbm2ddl ant task:

请看hbm2ddl ant任务的“update”属性:

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

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

update(default: false): Try and create an update script representing the "delta" between what is in the database and what the mappings specify. Ignores create/update attributes. (Do notuse against production databases, no guarantees at all that the proper delta can be generated nor that the underlying database can actually execute the needed operations)

更新(默认值:false):尝试创建一个更新脚本,表示数据库中的内容与映射指定的内容之间的“增量”。忽略创建/更新属性。(千万不能使用对生产数据库,不能保证在所有可以生成适当的增量也不是底层数据库可以实际执行所需的操作)