DB 移行 - Hibernate/JPA - hbm2ddl - diff ツール
質問
私が使う:
- EJB3 / JPA (休止状態)
- MySQL 5
データベースの移行を支援するシステムをセットアップする必要があります。LiquiBase を使用しようとしましたが、Hibernate で使用するにはまだ十分に成熟していないようです。
私がやりたいことは次のとおりです。
- アプリケーションのバージョン 1.0 が運用環境にあります
- アプリケーションのバージョン 2.0 を開発およびテストしました
- データを失わずに本番環境のアプリケーション データベースを更新したい
本当は新しいのを使いたいのですが、 persistence.xml
実稼働データベースでは、古いデータベースと新しいデータベースの間の「デルタ」を生成できるようになります。hbm2ddl が「更新」モードのときに実行される SQL コードを取得できるようにしたいと考えています。
この SQL コードは変更されます (drop+create=rename など)。 hbm2ddl.auto=update
.
Hibernateが新しいバージョンをデプロイするときにそれを行うので、それは可能だと思います hbm2ddl.auto=update
. 。しかし、Antタスクでそれを実行できるようにしたいのです hibernatetool
.
インターネット上でこれに関する情報があまり見つからないので、誰かがすでにここでそのようなことを行っていて、私を助けることができるのではないかと思います。
私は次のことを行いました:
<hibernatetool destdir="${dist}">
<!--
<jdbcconfiguration propertyfile="hibtest.properties"></jdbcconfiguration>
-->
<jpaconfiguration persistenceunit="server-pu" />
<classpath>
<fileset dir="${core.lib.server}" includes="*.jar" />
<fileset dir="${core.lib.runtime}" includes="*.jar" />
<fileset dir="${core.lib.build}" includes="*.jar" />
<pathelement location="${core.class}" />
<pathelement location="${core.etc}" />
</classpath>
<hbm2ddl outputfilename="schema-delta.sql" format="true"
export="false" update="true" />
</hibernatetool>
やり方がよくわかりません。作成SQLファイルは取得できましたが、デルタが欲しいだけです。update="true" を入力する必要がありますか?アプリケーションサーバーの外部の永続化ユニットでjpaconfigを使用できますか(db設定はGlassfishのJNDIリソースに設定されています)。(試してみましたが、データベースが見つかりませんでした)
私も試してみました <jdbcconfiguration propertyfile="hibtest.properties"></jdbcconfiguration>
またはデータベースのプロパティを設定します persistence.xml
JNDI リソースを使用する代わりに。
次のエラーが発生しました。
BUILD FAILED
/home/slorber/workspace/build/build.xml:899: org.hibernate.exception.JDBCConnectionException: Getting database metadata
at org.hibernate.tool.ant.HibernateToolTask.reportException(HibernateToolTask.java:226)
at org.hibernate.tool.ant.HibernateToolTask.execute(HibernateToolTask.java:189)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
at org.apache.tools.ant.Project.executeTarget(Project.java:1298)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.eclipse.ant.internal.ui.antsupport.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:32)
at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.run(InternalAntRunner.java:423)
at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.main(InternalAntRunner.java:137)
Caused by: org.hibernate.exception.JDBCConnectionException: Getting database metadata
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getMetaData(AbstractMetaDataDialect.java:64)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.caseForSearch(AbstractMetaDataDialect.java:163)
at org.hibernate.cfg.reveng.dialect.JDBCMetaDataDialect.getTables(JDBCMetaDataDialect.java:22)
at org.hibernate.cfg.reveng.JDBCReader.processTables(JDBCReader.java:476)
at org.hibernate.cfg.reveng.JDBCReader.readDatabaseSchema(JDBCReader.java:74)
at org.hibernate.cfg.reveng.JDBCReader.readDatabaseSchema(JDBCReader.java:860)
at org.hibernate.cfg.JDBCBinder.readDatabaseSchema(JDBCBinder.java:115)
at org.hibernate.cfg.JDBCBinder.readFromDatabase(JDBCBinder.java:88)
at org.hibernate.cfg.JDBCMetaDataConfiguration.readFromJDBC(JDBCMetaDataConfiguration.java:42)
at org.hibernate.tool.ant.JDBCConfigurationTask.doConfiguration(JDBCConfigurationTask.java:81)
at org.hibernate.tool.ant.ConfigurationTask.getConfiguration(ConfigurationTask.java:55)
at org.hibernate.tool.ant.HibernateToolTask.getConfiguration(HibernateToolTask.java:302)
at org.hibernate.tool.ant.Hbm2DDLExporterTask.createExporter(Hbm2DDLExporterTask.java:51)
at org.hibernate.tool.ant.ExporterTask.execute(ExporterTask.java:39)
at org.hibernate.tool.ant.HibernateToolTask.execute(HibernateToolTask.java:186)
... 15 more
Caused by: java.sql.SQLException: No suitable driver found for jdbc:mysql:3306//localhost/db
at java.sql.DriverManager.getConnection(DriverManager.java:602)
at java.sql.DriverManager.getConnection(DriverManager.java:154)
at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getConnection(AbstractMetaDataDialect.java:122)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getMetaData(AbstractMetaDataDialect.java:61)
... 29 more
--- Nested Exception ---
org.hibernate.exception.JDBCConnectionException: Getting database metadata
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getMetaData(AbstractMetaDataDialect.java:64)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.caseForSearch(AbstractMetaDataDialect.java:163)
at org.hibernate.cfg.reveng.dialect.JDBCMetaDataDialect.getTables(JDBCMetaDataDialect.java:22)
at org.hibernate.cfg.reveng.JDBCReader.processTables(JDBCReader.java:476)
at org.hibernate.cfg.reveng.JDBCReader.readDatabaseSchema(JDBCReader.java:74)
at org.hibernate.cfg.reveng.JDBCReader.readDatabaseSchema(JDBCReader.java:860)
at org.hibernate.cfg.JDBCBinder.readDatabaseSchema(JDBCBinder.java:115)
at org.hibernate.cfg.JDBCBinder.readFromDatabase(JDBCBinder.java:88)
at org.hibernate.cfg.JDBCMetaDataConfiguration.readFromJDBC(JDBCMetaDataConfiguration.java:42)
at org.hibernate.tool.ant.JDBCConfigurationTask.doConfiguration(JDBCConfigurationTask.java:81)
at org.hibernate.tool.ant.ConfigurationTask.getConfiguration(ConfigurationTask.java:55)
at org.hibernate.tool.ant.HibernateToolTask.getConfiguration(HibernateToolTask.java:302)
at org.hibernate.tool.ant.Hbm2DDLExporterTask.createExporter(Hbm2DDLExporterTask.java:51)
at org.hibernate.tool.ant.ExporterTask.execute(ExporterTask.java:39)
at org.hibernate.tool.ant.HibernateToolTask.execute(HibernateToolTask.java:186)
at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.tools.ant.dispatch.DispatchUtils.execute(DispatchUtils.java:105)
at org.apache.tools.ant.Task.perform(Task.java:348)
at org.apache.tools.ant.Target.execute(Target.java:357)
at org.apache.tools.ant.Target.performTasks(Target.java:385)
at org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
at org.apache.tools.ant.Project.executeTarget(Project.java:1298)
at org.apache.tools.ant.helper.DefaultExecutor.executeTargets(DefaultExecutor.java:41)
at org.eclipse.ant.internal.ui.antsupport.EclipseDefaultExecutor.executeTargets(EclipseDefaultExecutor.java:32)
at org.apache.tools.ant.Project.executeTargets(Project.java:1181)
at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.run(InternalAntRunner.java:423)
at org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.main(InternalAntRunner.java:137)
Caused by: java.sql.SQLException: No suitable driver found for jdbc:mysql:3306//localhost/db
at java.sql.DriverManager.getConnection(DriverManager.java:602)
at java.sql.DriverManager.getConnection(DriverManager.java:154)
at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getConnection(AbstractMetaDataDialect.java:122)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getMetaData(AbstractMetaDataDialect.java:61)
... 29 more
私は MySQL を使用しており、JDBC プロパティは次のとおりです。
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql:3306//localhost/db
hibernate.connection.username=root
hibernate.connection.password=root
hibernate.connection.show_sql=true
私のJDBC MySQLドライバーは ${core.lib.server}: mysql-connector-java-5.1.7-bin.jar
。(クラスパスも入れてみました <fileset dir="/home/slorber/workspace/core/lib/server" includes="*.jar" />
.)
また、Ant (Eclipse プラグイン) の実行構成クラスパスにも追加しました。
そこで私の質問は次のとおりです。
- やりたいことをやるために何か間違ったことをしてしまったのでしょうか?
- これは、Hibernate フレームワークを使用してデータベースを移行する方法ですか?(そして、すべての DB 変更を手作りの SQL ファイルに書き込まない場合、他に何をするでしょうか?)
解決
Hbm2ddlは自分で呼び出すことができるAPIを持っています。既存のAntタスクは、あなたが望むものをやっていない場合、あなたは常にhbm2ddlが可能性も文を実行ログに記録し、オーバーロードのJDBCドライバを休止状態に渡すのではなく、実際にそれらを実行するか、hbm2ddlがメソッドを実行するのオーバーロード、自分で通話を行うことができます。
私はまた、あなたがLiquiBaseをを使用し、差分の任意の並べ替えを介して手動でXMLファイルを作成するを見て必要があることを追加します。あなたが生成されたSQLが正しいことを検証する必要があることを認識し、それはあなたが開発する時にそれを一歩を作成することも簡単です、そして、あなたはそれが正しいことを知っている。
私たちは(など、列の名前を変更、列を追加し、テーブルを追加)休止状態、むしろ統合を休止状態LiquiBaseをを使用するよりも、私たちはHibernateのマッピングを更新し、彼らが失敗することを確認するために、当社の統合テストを実行し、必要なLiquiBaseをチェンジセットを作成して使用します、その後、テストを再実行し、それらを渡す参照してください。ステップで変更履歴のステップを構築することは健全性チェックを越えて何のためにdiffをするために頼ることなく、開発の定期的なリズムでうまく動作します。