回答:
いいえ、安全ではありません。
Hibernateチームの最善の努力にもかかわらず、本番環境では自動更新に依存することはできません。独自のパッチを作成し、DBAで確認してテストし、手動で適用します。
理論的には、hbm2ddl updateが開発で機能した場合、本番環境でも機能するはずです。しかし、実際には、常にそうであるとは限りません。
正常に機能しても、最適とは言えない可能性があります。DBAには理由があり、その分だけ給与が支払われます。
ミッションクリティカルではないアプリケーションを使用し、スタッフに高額なDBAがいない場合でも、本番環境でそれを行います。人為的エラーの影響を受けるのは、1つ少ない手動プロセスです。アプリケーションは違いを検出して正しいことを行うことができ、さらに、さまざまな開発環境やテスト環境でテストしたと考えられます。
注意点の1つ-クラスター環境では、複数のアプリが同時に表示されてスキーマを変更しようとする可能性があるため、これを回避することができます。または、1つのインスタンスのみがスキーマの更新を許可されるメカニズムを追加します。
Hibernateの作成者は、本「Java Persistence with Hibernate」の本番環境での使用を推奨していません。
警告:HibernateユーザーがSchemaUpdateを使用して本番データベースのスキーマを自動的に更新しようとしているのを見てきました。これは災害ですぐに終わり、DBAによって許可されません。
LiquiBase XMLをチェックして、更新の変更ログを保持してください。今年まで使用したことがありませんでしたが、DBのリビジョン管理/移行/変更管理を非常に簡単に習得して簡単にできることがわかりました。私はGroovy / Grailsプロジェクトに取り組んでおり、GrailsはそのすべてのORM(「GORM」と呼ばれます)にHibernateを使用しています。私たちはLiquibaseを使用してすべてのSQLスキーマの変更を管理します。これは、アプリが新機能で進化するにつれてかなり頻繁に行われます。
基本的に、アプリケーションの進化に応じて追加し続けるチェンジセットのXMLファイルを保持します。このファイルは、プロジェクトの残りの部分でgit(または使用しているもの)に保持されます。アプリがデプロイされると、Liquibaseは接続先のDBの変更ログテーブルをチェックして、すでに適用されているものを認識し、ファイルからまだ適用されていない変更セットをインテリジェントに適用します。これは実際には非常に優れており、すべてのスキーマ変更に使用すると、チェックアウトしてデプロイしたコードが常に完全に互換性のあるデータベーススキーマに接続できることを100%確信できます。
すばらしいのは、ラップトップで完全に空白のスレートmysqlデータベースを取得し、アプリを起動して、すぐにスキーマを設定できることです。また、スキーマの変更を最初にlocal-devまたはステージングデータベースに適用することで、スキーマの変更を簡単にテストできます。
これを使い始める最も簡単な方法は、おそらく既存のDBを取得してから、Liquibaseを使用して最初のbaseline.xmlファイルを生成することです。その後、あなたはそれに追加するだけで、liquibaseがスキーマの変更の管理を引き継ぐことができます。
hbm2ddl.auto=update
、クラス/ DBマッピングが検証され、リキベースを通じてDB作成を完全に制御できるように追加することになります。どう思いますか?
validate
私は反対票を投じるでしょう。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を超えてプッシュし、それがテキスト、ミディアムテキストなどに変換されるのを確認するなど、他の例もおそらくあるでしょう。
確かに、新しい列を作成し、データをコピーして古い列を吹き飛ばすことなく、「データ型を変換する」方法は実際にはないと思います。しかし、データベースに列が含まれている分、非常に危険に生きている現在のHibernateマッピングを反映していません...
Flywayは、この問題に対処するのに適したオプションです。
@Column(length = 45)
し@Column(length = 255)
ます。Hibernate 4.3.6.Finalがを使用してデータベーススキーマを正しく更新したことを確認できますhbm2ddl.auto=update
。(言及すべきことの1つは、現在データベースにはデータがなく、構造のみであるということです。)
Hibernateは、自動更新を使用しないことについての免責事項を製品で使用して、自分が何をしているのかわからない人が使用すべきでない状況でそれを使用する場合に備えて自分自身をカバーする必要があります。
それが使用されるべきではない状況が、大丈夫な状況よりもはるかに多いことを認めた。
私は何年にもわたってさまざまなプロジェクトで使用してきましたが、1つの問題が発生したことはありません。これは不十分な答えではなく、カウボーイコーディングでもありません。それは歴史的な事実です。
「本番環境では絶対に行わないでください」と言う人は、特定の本番デプロイメント、つまり彼がよく知っているデプロイメント(彼の会社、彼の業界など)について考えています。
「プロダクションデプロイメント」の世界は広大で多様です。
経験豊富なHibernate開発者は、特定のマッピング構成からどのDDLが生成されるかを正確に知っています。期待した結果がDDL(dev、qa、ステージングなど)に含まれることをテストおよび検証する限り、問題ありません。
多くの機能を追加する場合、自動スキーマ更新はリアルタイムの節約になります。
自動更新で処理されないもののリストは無限ですが、いくつかの例は、データの移行、null不可の列の追加、列名の変更などです。
また、クラスター環境では注意が必要です。
しかし、繰り返しになりますが、これらすべてを知っていれば、この質問をすることはないでしょう。うーん 。。。わかりました。この質問をする場合は、Hibernateと自動スキーマの更新に関する多くの経験があるまで待ってから、製品での使用を検討してください。
この記事で説明したようにhbm2ddl.auto
、本番環境で使用することはお勧めできません。
データベーススキーマを管理する唯一の方法は、次の理由で増分移行スクリプトを使用することです。
Hibernateユーザーガイドでも、hbm2ddl
本番環境でのツールの使用を避けるようにアドバイスしています。
SchemaExport
このテストケースで示されているように使用します。
私たちは、数か月間本番環境で実行されているプロジェクトでそれを行い、今のところ問題はありませんでした。このレシピに必要な2つの成分に留意してください。
下位互換性のあるアプローチでオブジェクトモデルを設計します。つまり、オブジェクトや属性を削除/変更するのではなく、廃止します。つまり、オブジェクトまたは属性の名前を変更する必要がある場合は、古い名前をそのままにして、新しい名前を追加し、ある種の移行スクリプトを記述します。オブジェクト間の関連付けを変更する必要がある場合、既に本番環境にいる場合、これはそもそも設計が間違っていたことを意味します。古いデータに影響を与えずに、新しい関係を表現する新しい方法を考えてみてください。
展開前に必ずデータベースをバックアップしてください。
私の感覚は、この記事を読んだ後、このディスカッションに参加している人々の90%が、このような自動化を本番環境で使用することを考えているだけで恐怖を感じることです。DBAにボールを投げる人もいます。少し時間を取って、すべての本番環境がDBAを提供するわけではなく、多くの開発チームがDBAを提供できるわけではないことを考慮してください(少なくとも中規模プロジェクトの場合)。だから、誰もがすべてをしなければならないチームについて話している場合、ボールは彼らの上にあります。
この場合、両方の長所を活かそうとしないでください。このようなツールは、注意深い設計と計画により、多くの状況で役立ちます。そして私を信じて、管理者は最初は納得するのが難しいかもしれませんが、ボールが自分の手にはないことを知っていれば、彼らはそれを気に入るはずです。
個人的には、あらゆる種類のスキーマを拡張するために手動でスクリプトを作成することはありませんが、それは私の意見です。そして、最近、NoSQLスキーマレスデータベースの採用を開始した後、これらのスキーマベースの操作はすべて過去のものであることがすぐにわかります。そのため、視点を変えて先を見るほうがよいでしょう。
保存されているはずのデータが失われる可能性があるので、リスクを冒しません。hbm2ddl.auto = updateは、開発データベースを最新の状態に保つための純粋に簡単な方法です。
私の場合(Hibernate 3.5.2、Postgresql、Ubuntu)、設定hibernate.hbm2ddl.auto=update
は新しいテーブルのみを作成し、既存のテーブルに新しい列を作成しました。
テーブルの削除も、列の削除も、列の変更も行いませんでした。それは安全なオプションと呼ぶことができますが、何かhibernate.hbm2ddl.auto=create_tables add_columns
がより明確になるでしょう。
安全ではなく、推奨されていませんが、可能です。
本番環境で自動更新オプションを使用するアプリケーションの経験があります。
このソリューションで見つかった主な問題とリスクは次のとおりです。
したがって、本番環境で自動更新を使用することはお勧めしません。
本番環境で自動更新を本当に使用したい場合は、以下をお勧めします。
そして、他の投稿とは異なり、自動更新が有効になっていて、「他の投稿で言及されているように」「非常に高額な」DBAに関連しているとは思いません。DBAには、SQLステートメントを記述してテーブルや列を作成、変更、削除するよりも、重要な作業があります。これらの単純な日常的なタスクは、開発者が実行および自動化でき、DBAチームがレビューするためにのみ渡され、HibernateとDBAがそれらを書くために「非常に有償」である必要はありません。
通常、大規模な組織のエンタープライズアプリケーションは、特権を減らして実行されます。
データベースユーザー名には、必要なDDL
列を追加する権限がない可能性がありhbm2ddl.auto=update
ます。
私はウラジミールに同意します。私の会社の管理者は、もし私がそのようなコースを提案したとしても、絶対に感謝しません。
さらに、Hibernateを盲目的に信頼する代わりにSQLスクリプトを作成すると、使用されなくなったフィールドを削除できます。Hibernateはそれを行いません。
また、プロダクションスキーマと新しいスキーマを比較すると、データモデルで変更したワットをさらに詳しく理解できることがわかります。もちろん、あなたはそれを作ったので知っていますが、今ではすべての変更を一度に見ることができます。「一体何を!?」みたいなものまで。
スキーマの差分を作成できるツールがあるため、大変な作業ではありません。そして、あなたは何が起こるかを正確に知っています。
アプリケーションのスキーマは時間とともに進化する可能性があります。異なるバージョンの複数のインストールがある場合、アプリケーション、ある種のツールまたはスクリプトがスキーマとデータをあるバージョンから次のバージョンに段階的に移行できることを確認する方法が必要です。
Hibernateマッピング(またはアノテーション)にすべての永続性を持たせることは、スキーマの進化を制御し続けるための非常に良い方法です。
スキーマの進化には、考慮すべきいくつかの側面があることを考慮する必要があります。
列とテーブルを追加する際のデータベーススキーマの進化
古い列、テーブル、リレーションの削除
新しい列をデフォルトで埋める
Hibernateツールは、(私の経験のように)同じアプリケーションの異なるバージョンがさまざまな種類のデータベースにある場合に特に重要です。
ポイント3は、Hibernateを使用している場合に非常に敏感です。たとえば、新しいブール値のプロパティまたは数値のプロパティを導入した場合、Hibernateがそのような列でnull値を検出した場合、例外が発生します。
だから私は何をしますか:スキーマ更新のHibernateツール機能を実際に使用しますが、それに加えて、デフォルトの入力、使用されなくなった列の削除など、データとスキーマのメンテナンスコールバックを追加する必要があります。このようにして、利点(データベースに依存しないスキーマ更新スクリプト、および永続性とスクリプトでの更新の重複したコーディングの回避)が得られますが、操作のすべての側面もカバーします。
したがって、たとえば、バージョン更新がvarchar値のプロパティ(したがって列)を追加するだけの場合、デフォルトではnullになり、自動更新が行われます。さらに複雑さが必要な場合は、より多くの作業が必要になります。
これは、更新されたアプリケーションがそのスキーマを更新できる(実行できる)ことを前提としています。これは、スキーマに対して更新するユーザー権限が必要であることも意味します。顧客のポリシーがこれを防止する場合(おそらくトカゲの脳の場合)、データベース(特定のスクリプト)を提供する必要があります。