Is it okay to run Hibernate applications configured with hbm2ddl.auto=update
to update the database schema in a production environment?
运行使用hbm2ddl配置的Hibernate应用程序可以吗?auto=update在生产环境中更新数据库模式?
15 个解决方案
#1
337
No, it's unsafe.
不,这是不安全的。
Despite the best efforts of the Hibernate team, you simply cannot rely on automatic updates in production. Write your own patches, review them with DBA, test them, then apply them manually.
尽管Hibernate团队尽了最大的努力,但您不能完全依赖于生产中的自动更新。编写您自己的补丁,与DBA一起检查它们,测试它们,然后手工应用它们。
Theoretically, if hbm2ddl update worked in development, it should work in production too. But in reality, it's not always the case.
理论上,如果hbm2ddl更新在开发中起作用,那么它也应该在生产中起作用。但事实上,并非总是如此。
Even if it worked OK, it may be sub-optimal. DBAs are paid that much for a reason.
即使运行良好,也可能是次优的。dba得到这么多报酬是有原因的。
#2
63
We do it in production albeit with an application that's not mission critical and with no highly paid DBAs on staff. It's just one less manual process that's subject to human error - the application can detect the difference and do the right thing, plus you've presumably tested it in various development and test environments.
我们在生产环境中进行此操作,尽管应用程序不是任务关键型的,而且员工中没有高薪的dba。这只是一个减少了人为错误的手工过程——应用程序可以检测差异并做正确的事情,而且您可能已经在各种开发和测试环境中对它进行了测试。
One caveat - in a clustered environment you may want to avoid it because multiple apps can come up at the same time and try to modify the schema which could be bad. Or put in some mechanism where only one instance is allowed to update the schema.
需要注意的是,在集群环境中,您可能希望避免使用它,因为多个应用程序可能同时出现,并试图修改可能很糟糕的模式。或者放入一些机制,其中只有一个实例被允许更新模式。
#3
44
Hibernate creators discourage doing so in a production environment in their book "Java Persistence with Hibernate":
Hibernate创建者在他们的《Java持久化与Hibernate》一书中不鼓励在生产环境中这样做:
WARNING: We've seen Hibernate users trying to use SchemaUpdate to update the schema of a production database automatically. This can quickly end in disaster and won't be allowed by your DBA.
警告:我们已经看到Hibernate用户试图使用SchemaUpdate自动更新生产数据库的模式。这可能很快导致灾难,您的DBA不允许这样做。
#4
27
Check out LiquiBase XML for keeping a changelog of updates. I had never used it until this year, but I found that it's very easy to learn and make DB revision control/migration/change management very foolproof. I work on a Groovy/Grails project, and Grails uses Hibernate underneath for all its ORM (called "GORM"). We use Liquibase to manage all SQL schema changes, which we do fairly often as our app evolves with new features.
查看LiquiBase XML来保持更新的变化量。我直到今年才使用它,但是我发现它非常容易学习,并且使DB修订控制/迁移/变更管理非常简单。我正在开发一个Groovy/Grails项目,Grails在其所有ORM(称为“GORM”)中都使用Hibernate。我们使用Liquibase来管理所有SQL模式更改,在我们的应用随着新特性的发展而变化时,我们经常这么做。
Basically, you keep an XML file of changesets that you continue to add to as your application evolves. This file is kept in git (or whatever you are using) with the rest of your project. When your app is deployed, Liquibase checks it's changelog table in the DB you are connecting to so it will know what has already been applied, then it intelligently just applies whatever changesets have not been applied yet from the file. It works absolutely great in practice, and if you use it for all your schema changes, then you can be 100% confident that code you checkout and deploy will always be able to connect to a fully compatible database schema.
基本上,您保留了一个变更集的XML文件,随着应用程序的发展,您将继续添加该文件。这个文件保存在git中(或者其他您正在使用的文件)和项目的其他部分。当您的应用程序被部署时,Liquibase会检查它在DB中的changelog表,这样它就知道已经应用了什么,然后智能地应用任何尚未应用到文件中的变更集。它在实践中非常有用,如果您对所有模式更改都使用它,那么您可以100%确信,您签出和部署的代码将始终能够连接到完全兼容的数据库模式。
The awesome thing is that I can take a totally blank slate mysql database on my laptop, fire up the app, and right away the schema is set up for me. It also makes it easy to test schema changes by applying these to a local-dev or staging db first.
最棒的是,我可以在我的笔记本电脑上建立一个完全空白的mysql数据库,启动应用程序,然后马上为我建立模式。它还可以通过先将模式更改应用到local-dev或staging db上来轻松地测试模式更改。
The easiest way to get started with it would probably be to take your existing DB and then use Liquibase to generate an initial baseline.xml file. Then in the future you can just append to it and let liquibase take over managing schema changes.
最简单的入门方法可能是使用现有的数据库,然后使用Liquibase生成初始基线。xml文件。然后在将来,您可以添加它,让liquibase接管管理模式更改。
http://www.liquibase.org/
#5
23
I would vote no. Hibernate doesn't seem to understand when datatypes for columns have changed. Examples (using MySQL):
我会投反对票。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
There are probably other examples as well, such as pushing the length of a String column up over 255 and seeing it convert to text, mediumtext, etc etc.
可能还有其他的例子,比如将字符串列的长度向上推到255以上,看到它被转换成文本、mediumtext等等。
Granted, I don't think there is really a way to "convert datatypes" with without creating a new column, copying the data and blowing away the old column. But the minute your database has columns which don't reflect the current Hibernate mapping you are living very dangerously...
当然,我认为确实没有一种方法可以在不创建新列、复制数据并删除旧列的情况下“转换数据类型”。但是,当您的数据库中有不反映当前Hibernate映射的列时,您就会非常危险……
Flyway is a good option to deal with this problem:
天桥是一个很好的选择来处理这个问题:
http://flywaydb.org
#6
18
Hibernate has to put the disclaimer about not using auto updates in prod to cover themselves when people who don't know what they are doing use it in situations where it should not be used.
当不知道自己在做什么的人在不应该使用它的情况下使用它时,Hibernate必须在prod中声明不要使用自动更新来掩盖自己。
Granted the situations where it should not be used greatly outnumber the ones where it's OK.
当然,在不应该使用它的情况下,它的数量远远超过了它可以使用的数量。
I have used it for years on lots of different projects and have never had a single issue. That's not a lame answer, and it's not cowboy coding. It's a historic fact.
我在许多不同的项目上使用了多年,从来没有一个问题。这不是一个蹩脚的回答,也不是牛仔编码。这是一个历史事实。
A person who says "never do it in production" is thinking of a specific set of production deployments, namely the ones he is familiar with (his company, his industry, etc).
一个说“永远不要在生产中做”的人正在考虑一组特定的生产部署,即他所熟悉的那些(他的公司、他的行业等等)。
The universe of "production deployments" is vast and varied.
“生产部署”的范围是广泛而多样的。
An experienced Hibernate developer knows exactly what DDL is going to result from a given mapping configuration. As long as you test and validate that what you expect ends up in the DDL (in dev, qa, staging, etc), you are fine.
经验丰富的Hibernate开发人员确切地知道给定映射配置将产生什么DDL。只要您测试并验证您所期望的结果在DDL(在dev、qa、登台等等)中结束,您就可以了。
When you are adding lots of features, auto schema updates can be a real time saver.
当您添加许多特性时,自动模式更新是一个真正的节省时间的方法。
The list of stuff auto updates won't handle is endless, but some examples are data migration, adding non-nullable columns, column name changes, etc, etc.
自动更新无法处理的内容列表是无穷无尽的,但是有些示例是数据迁移、添加不可空列、列名更改等等。
Also you need to take care in clustered environments.
您还需要在集群环境中小心。
But then again, if you knew all this stuff, you wouldn't be asking this question. Hmm . . . OK, if you are asking this question, you should wait until you have lots of experience with Hibernate and auto schema updates before you think about using it in prod.
但是,如果你知道这些,你就不会问这个问题了。嗯。。。好的,如果您正在问这个问题,您应该等到您对Hibernate和自动模式更新有了大量经验之后再考虑在prod中使用它。
#7
6
I wouldn't risk it because you might end up losing data that should have been preserved. hbm2ddl.auto=update is purely an easy way to keep your dev database up to date.
我不会冒险,因为你可能会丢失本应该保存的数据。hbm2ddl。auto=update纯粹是一种让开发数据库保持最新的简单方法。
#8
6
We do it in a project running in production for months now and never had a problem so far. Keep in mind the 2 ingredients needed for this recipe:
我们在一个在生产中运行了几个月的项目中这样做,到目前为止从来没有遇到过问题。记住这个食谱需要的两种成分:
-
Design your object model with a backwards-compatibility approach, that is deprecate objects and attributes rather than removing/altering them. This means that if you need to change the name of an object or attribute, leave the old one as is, add the new one and write some kind of migration script. If you need to change an association between objects, if you already are in production, this means that your design was wrong in the first place, so try to think of a new way of expressing the new relationship, without affecting old data.
使用向后兼容的方法来设计对象模型,即不赞成使用对象和属性,而不是删除/修改它们。这意味着,如果您需要更改对象或属性的名称,请保留旧的名称,添加新名称并编写某种迁移脚本。如果您需要更改对象之间的关联,如果您已经在生产中,这意味着您的设计首先是错误的,所以请尝试寻找一种新的方式来表达新关系,而不影响旧数据。
-
Always backup the database prior to deployment.
总是在部署之前备份数据库。
My sense is - after reading this post - that 90% of the people taking part in this discussion are horrified just with the thought of using automations like this in a production environment. Some throw the ball at the DBA. Take a moment though to consider that not all production environments will provide a DBA and not many dev teams are able to afford one (at least for medium size projects). So, if we're talking about teams where everyone has to do everything, the ball is on them.
在阅读这篇文章后,我的感觉是,90%参与讨论的人一想到在生产环境中使用这样的自动化就会感到震惊。有些人把球扔给DBA。花点时间考虑一下,不是所有的生产环境都能提供DBA,而不是许多开发团队能够负担得起(至少对于中等规模的项目)。所以,如果我们说的是每个人都要做所有事情的团队,那么问题就在他们身上。
In this case, why not just try to have the best of both worlds? Tools like this are here to give a helping hand, which - with a careful design and plan - can help in many situations. And believe me, administrators may initially be hard to convince but if they know that the ball is not on their hands, they will love it.
在这种情况下,为什么不试着拥有两个最好的世界呢?像这样的工具在这里提供帮助,在许多情况下,通过仔细的设计和计划可以帮助你。相信我,管理员一开始可能很难让人信服,但如果他们知道球不在他们手中,他们会喜欢的。
Personally, I'd never go back to writing scripts by hand for extending any type of schema, but that's just my opinion. And after starting to adopt NoSQL schema-less databases recently, I can see that more than soon, all these schema-based operations will belong to the past, so you'd better start changing your perspective and look ahead.
就我个人而言,我不会再为了扩展任何类型的模式而手工编写脚本,但这只是我的看法。在最近开始采用NoSQL无模式数据库之后,我可以很快看到,所有这些基于模式的操作都将属于过去,所以您最好开始改变您的观点并展望未来。
#9
6
As I explained in this article, it's not a good idea to use hbm2ddl.auto
in production.
正如我在本文中解释的,使用hbm2ddl不是一个好主意。汽车在生产。
The only way to manage the database schema is to use incremental migration scripts because:
管理数据库模式的惟一方法是使用增量迁移脚本,因为:
- the scripts will reside in VCS along your code base. When you checkout a branch, you recreate the whole schema from scratch.
- 脚本将驻留在VCS中的代码库中。当您签出一个分支时,您将从头重新创建整个模式。
- the incremental scripts can be tested on a QA server before being applied in production
- 增量脚本可以在产品中应用之前在QA服务器上进行测试
- there is no need for manual intervention since the scripts can be run by Flyway, hence it reduces the possibility of human error associated with running scripts manually.
- 无需手动干预,因为脚本可以通过Flyway运行,因此它减少了手工运行脚本时发生人为错误的可能性。
Even the Hibernate User Guide advise you to avoid using the hbm2ddl
tool for production environments.
甚至Hibernate用户指南也建议您避免在生产环境中使用hbm2ddl工具。
#10
5
No, don't ever do it. Hibernate does not handle data migration. Yes, it will make your schema look correctly but it does not ensure that valuable production data is not lost in the process.
不,千万别这么做。Hibernate不处理数据迁移。是的,它将使您的模式看起来正确,但是它不能确保在过程中没有丢失有价值的生产数据。
#11
4
It's not safe, not recommended, but it's possible.
它不安全,不推荐,但它是可能的。
I have experience in an application using the auto-update option in production.
我有在生产中使用自动更新选项的应用程序的经验。
Well, the main problems and risks found in this solution are:
这个解决方案的主要问题和风险是:
- 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.
- 在错误的数据库中部署。如果您在错误的数据库中使用旧版本的应用程序(EAR/WAR/等)运行应用服务器,那么……您将拥有许多新的列、表、外键和错误。同样的问题可能发生在datasource文件中的一个简单错误(复制/粘贴文件,忘记更改数据库)。在简历中,这种情况可能是数据库中的灾难。
- 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 does this to know what (table, column, etc) need to be created. This problem will only gets worse.
- 应用服务器启动时间太长。这是因为Hibernate每次启动应用程序时都试图查找所有创建的表/列/等等。他这样做是为了知道需要创建什么(表、列等)。这个问题只会变得更糟。
- Database tools it's almost impossible to use. To create scripts for the database, you need to think about what will be created by the auto-update after you start the application server. If you need to fill a new column (per example) with some data, you need to start the application server, wait to Hibernate crete the new column and run the SQL script after that. Tools like Flyway it's almost impossible to use with auto-update enabled.
- 几乎不可能使用数据库工具。要为数据库创建脚本,您需要考虑在启动应用服务器后自动更新将创建什么。如果需要用一些数据填充新列(每个示例),则需要启动应用服务器,等待Hibernate crete新列,然后运行SQL脚本。像Flyway这样的工具,几乎不可能在启用自动更新的情况下使用。
- Database changes is not centralized. With the possibility of the Hibernate create the tables and everything else, it's hard to watch the changes on database in each version of the application, because most of them are automatically.
- 数据库更改不是集中的。由于Hibernate可以创建表和其他东西,因此很难观察应用程序每个版本中数据库上的更改,因为大多数更改都是自动的。
- Encourages garbage on database. Because of the ease of auto-update, there is a chance your team neglecting to drop old columns and old tables.
- 鼓励垃圾对数据库。由于自动更新很容易,您的团队可能会忽略掉旧的列和旧的表。
- 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 updatable for years, I don't think it's safe. I never felt safe.
- 迫在眉睫的灾难。生产中出现一些灾难的迫在眉睫的风险(如其他答案中提到的一些人)。即使一个应用程序可以运行和更新好几年,我也不认为它是安全的。我从来没有感到安全。
So, I will not recommend to use auto-update in production.
因此,我不建议在生产中使用自动更新。
If you really want to use auto-update in production, I recommend:
如果你真的想在生产中使用自动更新,我建议:
- Separated networks. Your test environment cannot access the homolog environment. This helps prevent a deployment that was supposed to be in the Test environment change the Homologation database.
- 网络分开。您的测试环境无法访问homolog环境。这有助于防止在测试环境中出现的部署更改相应的数据库。
- Manage scripts order. You need to organize your scripts to run before your deploy (structure table change, drop table/columns) and script after the deploy (fill information for the new columns/tables).
- 订单管理脚本。在部署之前(结构表更改、删除表/列)和部署之后(为新列/表填充信息),您需要组织脚本。
And, different of the another posts, I don't think the auto-update enabled it's related with "very well paid" DBAs (as mentioned in other posts)... DBAs have more important things to do than write SQL statements to create/change/delete tables and columns. These simple everyday tasks can be done and automated by developers and only passed for DBA team to review, not needing Hibernate and DBAs "very well paid" to write them.
而且,与其他文章不同的是,我不认为自动更新与“非常高薪”的dba(如其他文章所提到的)有关……dba有比编写SQL语句来创建/更改/删除表和列更重要的事情要做。这些简单的日常任务可以由开发人员完成并自动完成,并且只通过DBA团队进行检查,不需要Hibernate和DBA“非常高薪”来编写它们。
#12
3
-
In my case (Hibernate 3.5.2, Postgresql, Ubuntu), setting
hibernate.hbm2ddl.auto=update
only created new tables and created new columns in already existing tables.在我的例子中(Hibernate 3.5.2、Postgresql、Ubuntu),设置Hibernate .hbm2ddl。auto=update只创建新表,并在现有表中创建新列。
-
It did neither drop tables, nor drop columns, nor alter columns. It can be called a safe option, but something like
hibernate.hbm2ddl.auto=create_tables add_columns
would be more clear.它既不删除表,也不删除列,也不修改列。它可以被称为安全选项,但类似hibernate.hbm2ddl。auto=create_tables add_columns更清晰。
#13
3
-
Typically enterprise applications in large organizations run with reduced privileges.
大型组织中的企业应用程序通常以减少的特权运行。
-
Database username may not have
DDL
privilege for adding columns whichhbm2ddl.auto=update
requires.数据库用户名可能没有用于添加hbm2ddl的列的DDL特权。汽车=更新要求。
#14
2
I agree with Vladimir. The administrators in my company would definitely not appreciate it if I even suggested such a course.
我同意弗拉基米尔。如果我建议这样的课程,我公司的管理人员肯定不会感激。
Further, creating an SQL script in stead of blindly trusting Hibernate gives you the opportunity to remove fields which are no longer in use. Hibernate does not do that.
此外,创建一个SQL脚本而不是盲目信任Hibernate,可以让您删除不再使用的字段。Hibernate不这么做。
And I find comparing the production schema with the new schema gives you even better insight to wat you changed in the data model. You know, of course, because you made it, but now you see all the changes in one go. Even the ones which make you go like "What the heck?!".
我发现,将生产模式与新模式进行比较,可以让您更好地了解数据模型中更改的wat。你知道,当然,因为你做到了,但是现在你看到了所有的变化。甚至那些让你说“管它呢?!”
There are tools which can make a schema delta for you, so it isn't even hard work. And then you know exactly what's going to happen.
有一些工具可以为您创建模式增量,因此这甚至不是一项艰苦的工作。然后你就知道会发生什么。
#15
2
Applications' schema may evolve in time; if you have several installations, which may be at different versions, you should have some way to ensure that your application, some kind of tool or script is capable of migrating schema and data from one version stepwise to any following one.
应用程序的模式可能会随着时间的推移而变化;如果您有几个安装(可能在不同的版本中),您应该有某种方法来确保您的应用程序、某种工具或脚本能够逐步地将模式和数据从一个版本迁移到下一个版本。
Having all your persistence in Hibernate mappings (or annotations) is a very good way for keeping schema evolution under control.
使用Hibernate映射(或注释)中的所有持久性是控制模式演化的一种非常好的方法。
You should consider that schema evolution has several aspects to be considered:
您应该考虑模式进化有几个方面需要考虑:
-
evolution of the database schema in adding more columns and tables
数据库模式在添加更多列和表方面的发展
-
dropping of old columns, tables and relations
删除旧列、表和关系
-
filling new columns with defaults
用默认值填充新列
Hibernate tools are important in particular in case (like in my experience) you have different versions of the same application on many different kinds of databases.
Hibernate工具特别重要(就像我的经验一样),您在许多不同类型的数据库上拥有相同应用程序的不同版本。
Point 3 is very sensitive in case you are using Hibernate, as in case you introduce a new boolean valued property or numeric one, if Hibernate will find any null value in such columns, if will raise an exception.
点3在使用Hibernate时非常敏感,比如引入新的布尔值属性或数字属性时,如果Hibernate在这些列中找到任何空值,如果会引发异常。
So what I would do is: do indeed use the Hibernate tools capacity of schema update, but you must add alongside of it some data and schema maintenance callback, like for filling defaults, dropping no longer used columns, and similar. In this way you get the advantages (database independent schema update scripts and avoiding duplicated coding of the updates, in peristence and in scripts) but you also cover all the aspects of the operation.
因此,我要做的是:确实要使用Hibernate工具的模式更新功能,但是必须在其中添加一些数据和模式维护回调,比如填充默认值、删除不再使用的列等等。通过这种方式,您可以获得优势(独立于数据库的模式更新脚本和避免更新的重复编码,在周期和脚本中),但您也可以涵盖操作的所有方面。
So for example if a version update consists simply in adding a varchar valued property (hence column), which may default to null, with auto update you'll be done. Where more complexity is necessary, more work will be necessary.
因此,例如,如果一个版本更新仅仅是添加一个varchar值属性(因此列),它可能默认为null,那么自动更新就完成了。如果需要更多的复杂性,就需要更多的工作。
This is assuming that the application when updated is capable of updating its schema (it can be done), which also means that it must have the user rights to do so on the schema. If the policy of the customer prevents this (likely Lizard Brain case), you will have to provide the database - specific scripts.
这是假设更新后的应用程序能够更新它的模式(它是可以完成的),这也意味着它必须具有对模式进行更新的用户权限。如果客户的策略防止了这种情况(可能是蜥蜴脑的情况),您将必须提供特定于数据库的脚本。
#1
337
No, it's unsafe.
不,这是不安全的。
Despite the best efforts of the Hibernate team, you simply cannot rely on automatic updates in production. Write your own patches, review them with DBA, test them, then apply them manually.
尽管Hibernate团队尽了最大的努力,但您不能完全依赖于生产中的自动更新。编写您自己的补丁,与DBA一起检查它们,测试它们,然后手工应用它们。
Theoretically, if hbm2ddl update worked in development, it should work in production too. But in reality, it's not always the case.
理论上,如果hbm2ddl更新在开发中起作用,那么它也应该在生产中起作用。但事实上,并非总是如此。
Even if it worked OK, it may be sub-optimal. DBAs are paid that much for a reason.
即使运行良好,也可能是次优的。dba得到这么多报酬是有原因的。
#2
63
We do it in production albeit with an application that's not mission critical and with no highly paid DBAs on staff. It's just one less manual process that's subject to human error - the application can detect the difference and do the right thing, plus you've presumably tested it in various development and test environments.
我们在生产环境中进行此操作,尽管应用程序不是任务关键型的,而且员工中没有高薪的dba。这只是一个减少了人为错误的手工过程——应用程序可以检测差异并做正确的事情,而且您可能已经在各种开发和测试环境中对它进行了测试。
One caveat - in a clustered environment you may want to avoid it because multiple apps can come up at the same time and try to modify the schema which could be bad. Or put in some mechanism where only one instance is allowed to update the schema.
需要注意的是,在集群环境中,您可能希望避免使用它,因为多个应用程序可能同时出现,并试图修改可能很糟糕的模式。或者放入一些机制,其中只有一个实例被允许更新模式。
#3
44
Hibernate creators discourage doing so in a production environment in their book "Java Persistence with Hibernate":
Hibernate创建者在他们的《Java持久化与Hibernate》一书中不鼓励在生产环境中这样做:
WARNING: We've seen Hibernate users trying to use SchemaUpdate to update the schema of a production database automatically. This can quickly end in disaster and won't be allowed by your DBA.
警告:我们已经看到Hibernate用户试图使用SchemaUpdate自动更新生产数据库的模式。这可能很快导致灾难,您的DBA不允许这样做。
#4
27
Check out LiquiBase XML for keeping a changelog of updates. I had never used it until this year, but I found that it's very easy to learn and make DB revision control/migration/change management very foolproof. I work on a Groovy/Grails project, and Grails uses Hibernate underneath for all its ORM (called "GORM"). We use Liquibase to manage all SQL schema changes, which we do fairly often as our app evolves with new features.
查看LiquiBase XML来保持更新的变化量。我直到今年才使用它,但是我发现它非常容易学习,并且使DB修订控制/迁移/变更管理非常简单。我正在开发一个Groovy/Grails项目,Grails在其所有ORM(称为“GORM”)中都使用Hibernate。我们使用Liquibase来管理所有SQL模式更改,在我们的应用随着新特性的发展而变化时,我们经常这么做。
Basically, you keep an XML file of changesets that you continue to add to as your application evolves. This file is kept in git (or whatever you are using) with the rest of your project. When your app is deployed, Liquibase checks it's changelog table in the DB you are connecting to so it will know what has already been applied, then it intelligently just applies whatever changesets have not been applied yet from the file. It works absolutely great in practice, and if you use it for all your schema changes, then you can be 100% confident that code you checkout and deploy will always be able to connect to a fully compatible database schema.
基本上,您保留了一个变更集的XML文件,随着应用程序的发展,您将继续添加该文件。这个文件保存在git中(或者其他您正在使用的文件)和项目的其他部分。当您的应用程序被部署时,Liquibase会检查它在DB中的changelog表,这样它就知道已经应用了什么,然后智能地应用任何尚未应用到文件中的变更集。它在实践中非常有用,如果您对所有模式更改都使用它,那么您可以100%确信,您签出和部署的代码将始终能够连接到完全兼容的数据库模式。
The awesome thing is that I can take a totally blank slate mysql database on my laptop, fire up the app, and right away the schema is set up for me. It also makes it easy to test schema changes by applying these to a local-dev or staging db first.
最棒的是,我可以在我的笔记本电脑上建立一个完全空白的mysql数据库,启动应用程序,然后马上为我建立模式。它还可以通过先将模式更改应用到local-dev或staging db上来轻松地测试模式更改。
The easiest way to get started with it would probably be to take your existing DB and then use Liquibase to generate an initial baseline.xml file. Then in the future you can just append to it and let liquibase take over managing schema changes.
最简单的入门方法可能是使用现有的数据库,然后使用Liquibase生成初始基线。xml文件。然后在将来,您可以添加它,让liquibase接管管理模式更改。
http://www.liquibase.org/
#5
23
I would vote no. Hibernate doesn't seem to understand when datatypes for columns have changed. Examples (using MySQL):
我会投反对票。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
There are probably other examples as well, such as pushing the length of a String column up over 255 and seeing it convert to text, mediumtext, etc etc.
可能还有其他的例子,比如将字符串列的长度向上推到255以上,看到它被转换成文本、mediumtext等等。
Granted, I don't think there is really a way to "convert datatypes" with without creating a new column, copying the data and blowing away the old column. But the minute your database has columns which don't reflect the current Hibernate mapping you are living very dangerously...
当然,我认为确实没有一种方法可以在不创建新列、复制数据并删除旧列的情况下“转换数据类型”。但是,当您的数据库中有不反映当前Hibernate映射的列时,您就会非常危险……
Flyway is a good option to deal with this problem:
天桥是一个很好的选择来处理这个问题:
http://flywaydb.org
#6
18
Hibernate has to put the disclaimer about not using auto updates in prod to cover themselves when people who don't know what they are doing use it in situations where it should not be used.
当不知道自己在做什么的人在不应该使用它的情况下使用它时,Hibernate必须在prod中声明不要使用自动更新来掩盖自己。
Granted the situations where it should not be used greatly outnumber the ones where it's OK.
当然,在不应该使用它的情况下,它的数量远远超过了它可以使用的数量。
I have used it for years on lots of different projects and have never had a single issue. That's not a lame answer, and it's not cowboy coding. It's a historic fact.
我在许多不同的项目上使用了多年,从来没有一个问题。这不是一个蹩脚的回答,也不是牛仔编码。这是一个历史事实。
A person who says "never do it in production" is thinking of a specific set of production deployments, namely the ones he is familiar with (his company, his industry, etc).
一个说“永远不要在生产中做”的人正在考虑一组特定的生产部署,即他所熟悉的那些(他的公司、他的行业等等)。
The universe of "production deployments" is vast and varied.
“生产部署”的范围是广泛而多样的。
An experienced Hibernate developer knows exactly what DDL is going to result from a given mapping configuration. As long as you test and validate that what you expect ends up in the DDL (in dev, qa, staging, etc), you are fine.
经验丰富的Hibernate开发人员确切地知道给定映射配置将产生什么DDL。只要您测试并验证您所期望的结果在DDL(在dev、qa、登台等等)中结束,您就可以了。
When you are adding lots of features, auto schema updates can be a real time saver.
当您添加许多特性时,自动模式更新是一个真正的节省时间的方法。
The list of stuff auto updates won't handle is endless, but some examples are data migration, adding non-nullable columns, column name changes, etc, etc.
自动更新无法处理的内容列表是无穷无尽的,但是有些示例是数据迁移、添加不可空列、列名更改等等。
Also you need to take care in clustered environments.
您还需要在集群环境中小心。
But then again, if you knew all this stuff, you wouldn't be asking this question. Hmm . . . OK, if you are asking this question, you should wait until you have lots of experience with Hibernate and auto schema updates before you think about using it in prod.
但是,如果你知道这些,你就不会问这个问题了。嗯。。。好的,如果您正在问这个问题,您应该等到您对Hibernate和自动模式更新有了大量经验之后再考虑在prod中使用它。
#7
6
I wouldn't risk it because you might end up losing data that should have been preserved. hbm2ddl.auto=update is purely an easy way to keep your dev database up to date.
我不会冒险,因为你可能会丢失本应该保存的数据。hbm2ddl。auto=update纯粹是一种让开发数据库保持最新的简单方法。
#8
6
We do it in a project running in production for months now and never had a problem so far. Keep in mind the 2 ingredients needed for this recipe:
我们在一个在生产中运行了几个月的项目中这样做,到目前为止从来没有遇到过问题。记住这个食谱需要的两种成分:
-
Design your object model with a backwards-compatibility approach, that is deprecate objects and attributes rather than removing/altering them. This means that if you need to change the name of an object or attribute, leave the old one as is, add the new one and write some kind of migration script. If you need to change an association between objects, if you already are in production, this means that your design was wrong in the first place, so try to think of a new way of expressing the new relationship, without affecting old data.
使用向后兼容的方法来设计对象模型,即不赞成使用对象和属性,而不是删除/修改它们。这意味着,如果您需要更改对象或属性的名称,请保留旧的名称,添加新名称并编写某种迁移脚本。如果您需要更改对象之间的关联,如果您已经在生产中,这意味着您的设计首先是错误的,所以请尝试寻找一种新的方式来表达新关系,而不影响旧数据。
-
Always backup the database prior to deployment.
总是在部署之前备份数据库。
My sense is - after reading this post - that 90% of the people taking part in this discussion are horrified just with the thought of using automations like this in a production environment. Some throw the ball at the DBA. Take a moment though to consider that not all production environments will provide a DBA and not many dev teams are able to afford one (at least for medium size projects). So, if we're talking about teams where everyone has to do everything, the ball is on them.
在阅读这篇文章后,我的感觉是,90%参与讨论的人一想到在生产环境中使用这样的自动化就会感到震惊。有些人把球扔给DBA。花点时间考虑一下,不是所有的生产环境都能提供DBA,而不是许多开发团队能够负担得起(至少对于中等规模的项目)。所以,如果我们说的是每个人都要做所有事情的团队,那么问题就在他们身上。
In this case, why not just try to have the best of both worlds? Tools like this are here to give a helping hand, which - with a careful design and plan - can help in many situations. And believe me, administrators may initially be hard to convince but if they know that the ball is not on their hands, they will love it.
在这种情况下,为什么不试着拥有两个最好的世界呢?像这样的工具在这里提供帮助,在许多情况下,通过仔细的设计和计划可以帮助你。相信我,管理员一开始可能很难让人信服,但如果他们知道球不在他们手中,他们会喜欢的。
Personally, I'd never go back to writing scripts by hand for extending any type of schema, but that's just my opinion. And after starting to adopt NoSQL schema-less databases recently, I can see that more than soon, all these schema-based operations will belong to the past, so you'd better start changing your perspective and look ahead.
就我个人而言,我不会再为了扩展任何类型的模式而手工编写脚本,但这只是我的看法。在最近开始采用NoSQL无模式数据库之后,我可以很快看到,所有这些基于模式的操作都将属于过去,所以您最好开始改变您的观点并展望未来。
#9
6
As I explained in this article, it's not a good idea to use hbm2ddl.auto
in production.
正如我在本文中解释的,使用hbm2ddl不是一个好主意。汽车在生产。
The only way to manage the database schema is to use incremental migration scripts because:
管理数据库模式的惟一方法是使用增量迁移脚本,因为:
- the scripts will reside in VCS along your code base. When you checkout a branch, you recreate the whole schema from scratch.
- 脚本将驻留在VCS中的代码库中。当您签出一个分支时,您将从头重新创建整个模式。
- the incremental scripts can be tested on a QA server before being applied in production
- 增量脚本可以在产品中应用之前在QA服务器上进行测试
- there is no need for manual intervention since the scripts can be run by Flyway, hence it reduces the possibility of human error associated with running scripts manually.
- 无需手动干预,因为脚本可以通过Flyway运行,因此它减少了手工运行脚本时发生人为错误的可能性。
Even the Hibernate User Guide advise you to avoid using the hbm2ddl
tool for production environments.
甚至Hibernate用户指南也建议您避免在生产环境中使用hbm2ddl工具。
#10
5
No, don't ever do it. Hibernate does not handle data migration. Yes, it will make your schema look correctly but it does not ensure that valuable production data is not lost in the process.
不,千万别这么做。Hibernate不处理数据迁移。是的,它将使您的模式看起来正确,但是它不能确保在过程中没有丢失有价值的生产数据。
#11
4
It's not safe, not recommended, but it's possible.
它不安全,不推荐,但它是可能的。
I have experience in an application using the auto-update option in production.
我有在生产中使用自动更新选项的应用程序的经验。
Well, the main problems and risks found in this solution are:
这个解决方案的主要问题和风险是:
- 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.
- 在错误的数据库中部署。如果您在错误的数据库中使用旧版本的应用程序(EAR/WAR/等)运行应用服务器,那么……您将拥有许多新的列、表、外键和错误。同样的问题可能发生在datasource文件中的一个简单错误(复制/粘贴文件,忘记更改数据库)。在简历中,这种情况可能是数据库中的灾难。
- 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 does this to know what (table, column, etc) need to be created. This problem will only gets worse.
- 应用服务器启动时间太长。这是因为Hibernate每次启动应用程序时都试图查找所有创建的表/列/等等。他这样做是为了知道需要创建什么(表、列等)。这个问题只会变得更糟。
- Database tools it's almost impossible to use. To create scripts for the database, you need to think about what will be created by the auto-update after you start the application server. If you need to fill a new column (per example) with some data, you need to start the application server, wait to Hibernate crete the new column and run the SQL script after that. Tools like Flyway it's almost impossible to use with auto-update enabled.
- 几乎不可能使用数据库工具。要为数据库创建脚本,您需要考虑在启动应用服务器后自动更新将创建什么。如果需要用一些数据填充新列(每个示例),则需要启动应用服务器,等待Hibernate crete新列,然后运行SQL脚本。像Flyway这样的工具,几乎不可能在启用自动更新的情况下使用。
- Database changes is not centralized. With the possibility of the Hibernate create the tables and everything else, it's hard to watch the changes on database in each version of the application, because most of them are automatically.
- 数据库更改不是集中的。由于Hibernate可以创建表和其他东西,因此很难观察应用程序每个版本中数据库上的更改,因为大多数更改都是自动的。
- Encourages garbage on database. Because of the ease of auto-update, there is a chance your team neglecting to drop old columns and old tables.
- 鼓励垃圾对数据库。由于自动更新很容易,您的团队可能会忽略掉旧的列和旧的表。
- 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 updatable for years, I don't think it's safe. I never felt safe.
- 迫在眉睫的灾难。生产中出现一些灾难的迫在眉睫的风险(如其他答案中提到的一些人)。即使一个应用程序可以运行和更新好几年,我也不认为它是安全的。我从来没有感到安全。
So, I will not recommend to use auto-update in production.
因此,我不建议在生产中使用自动更新。
If you really want to use auto-update in production, I recommend:
如果你真的想在生产中使用自动更新,我建议:
- Separated networks. Your test environment cannot access the homolog environment. This helps prevent a deployment that was supposed to be in the Test environment change the Homologation database.
- 网络分开。您的测试环境无法访问homolog环境。这有助于防止在测试环境中出现的部署更改相应的数据库。
- Manage scripts order. You need to organize your scripts to run before your deploy (structure table change, drop table/columns) and script after the deploy (fill information for the new columns/tables).
- 订单管理脚本。在部署之前(结构表更改、删除表/列)和部署之后(为新列/表填充信息),您需要组织脚本。
And, different of the another posts, I don't think the auto-update enabled it's related with "very well paid" DBAs (as mentioned in other posts)... DBAs have more important things to do than write SQL statements to create/change/delete tables and columns. These simple everyday tasks can be done and automated by developers and only passed for DBA team to review, not needing Hibernate and DBAs "very well paid" to write them.
而且,与其他文章不同的是,我不认为自动更新与“非常高薪”的dba(如其他文章所提到的)有关……dba有比编写SQL语句来创建/更改/删除表和列更重要的事情要做。这些简单的日常任务可以由开发人员完成并自动完成,并且只通过DBA团队进行检查,不需要Hibernate和DBA“非常高薪”来编写它们。
#12
3
-
In my case (Hibernate 3.5.2, Postgresql, Ubuntu), setting
hibernate.hbm2ddl.auto=update
only created new tables and created new columns in already existing tables.在我的例子中(Hibernate 3.5.2、Postgresql、Ubuntu),设置Hibernate .hbm2ddl。auto=update只创建新表,并在现有表中创建新列。
-
It did neither drop tables, nor drop columns, nor alter columns. It can be called a safe option, but something like
hibernate.hbm2ddl.auto=create_tables add_columns
would be more clear.它既不删除表,也不删除列,也不修改列。它可以被称为安全选项,但类似hibernate.hbm2ddl。auto=create_tables add_columns更清晰。
#13
3
-
Typically enterprise applications in large organizations run with reduced privileges.
大型组织中的企业应用程序通常以减少的特权运行。
-
Database username may not have
DDL
privilege for adding columns whichhbm2ddl.auto=update
requires.数据库用户名可能没有用于添加hbm2ddl的列的DDL特权。汽车=更新要求。
#14
2
I agree with Vladimir. The administrators in my company would definitely not appreciate it if I even suggested such a course.
我同意弗拉基米尔。如果我建议这样的课程,我公司的管理人员肯定不会感激。
Further, creating an SQL script in stead of blindly trusting Hibernate gives you the opportunity to remove fields which are no longer in use. Hibernate does not do that.
此外,创建一个SQL脚本而不是盲目信任Hibernate,可以让您删除不再使用的字段。Hibernate不这么做。
And I find comparing the production schema with the new schema gives you even better insight to wat you changed in the data model. You know, of course, because you made it, but now you see all the changes in one go. Even the ones which make you go like "What the heck?!".
我发现,将生产模式与新模式进行比较,可以让您更好地了解数据模型中更改的wat。你知道,当然,因为你做到了,但是现在你看到了所有的变化。甚至那些让你说“管它呢?!”
There are tools which can make a schema delta for you, so it isn't even hard work. And then you know exactly what's going to happen.
有一些工具可以为您创建模式增量,因此这甚至不是一项艰苦的工作。然后你就知道会发生什么。
#15
2
Applications' schema may evolve in time; if you have several installations, which may be at different versions, you should have some way to ensure that your application, some kind of tool or script is capable of migrating schema and data from one version stepwise to any following one.
应用程序的模式可能会随着时间的推移而变化;如果您有几个安装(可能在不同的版本中),您应该有某种方法来确保您的应用程序、某种工具或脚本能够逐步地将模式和数据从一个版本迁移到下一个版本。
Having all your persistence in Hibernate mappings (or annotations) is a very good way for keeping schema evolution under control.
使用Hibernate映射(或注释)中的所有持久性是控制模式演化的一种非常好的方法。
You should consider that schema evolution has several aspects to be considered:
您应该考虑模式进化有几个方面需要考虑:
-
evolution of the database schema in adding more columns and tables
数据库模式在添加更多列和表方面的发展
-
dropping of old columns, tables and relations
删除旧列、表和关系
-
filling new columns with defaults
用默认值填充新列
Hibernate tools are important in particular in case (like in my experience) you have different versions of the same application on many different kinds of databases.
Hibernate工具特别重要(就像我的经验一样),您在许多不同类型的数据库上拥有相同应用程序的不同版本。
Point 3 is very sensitive in case you are using Hibernate, as in case you introduce a new boolean valued property or numeric one, if Hibernate will find any null value in such columns, if will raise an exception.
点3在使用Hibernate时非常敏感,比如引入新的布尔值属性或数字属性时,如果Hibernate在这些列中找到任何空值,如果会引发异常。
So what I would do is: do indeed use the Hibernate tools capacity of schema update, but you must add alongside of it some data and schema maintenance callback, like for filling defaults, dropping no longer used columns, and similar. In this way you get the advantages (database independent schema update scripts and avoiding duplicated coding of the updates, in peristence and in scripts) but you also cover all the aspects of the operation.
因此,我要做的是:确实要使用Hibernate工具的模式更新功能,但是必须在其中添加一些数据和模式维护回调,比如填充默认值、删除不再使用的列等等。通过这种方式,您可以获得优势(独立于数据库的模式更新脚本和避免更新的重复编码,在周期和脚本中),但您也可以涵盖操作的所有方面。
So for example if a version update consists simply in adding a varchar valued property (hence column), which may default to null, with auto update you'll be done. Where more complexity is necessary, more work will be necessary.
因此,例如,如果一个版本更新仅仅是添加一个varchar值属性(因此列),它可能默认为null,那么自动更新就完成了。如果需要更多的复杂性,就需要更多的工作。
This is assuming that the application when updated is capable of updating its schema (it can be done), which also means that it must have the user rights to do so on the schema. If the policy of the customer prevents this (likely Lizard Brain case), you will have to provide the database - specific scripts.
这是假设更新后的应用程序能够更新它的模式(它是可以完成的),这也意味着它必须具有对模式进行更新的用户权限。如果客户的策略防止了这种情况(可能是蜥蜴脑的情况),您将必须提供特定于数据库的脚本。