Миграция базы данных – Hibernate/JPA – hbm2ddl – инструменты сравнения

StackOverflow https://stackoverflow.com/questions/1142447

Вопрос

Я использую:

  • EJB3/JPA (спящий режим)
  • MySQL 5

Мне нужно настроить систему для облегчения миграции баз данных.Пытался использовать LiquiBase, но, похоже, он еще недостаточно зрел для использования с Hibernate.

Я хотел бы сделать следующее:

  • У меня есть версия 1.0 приложения в производстве.
  • У меня разработана и протестирована версия 2.0 приложения.
  • Я хочу обновить базу данных приложения в производстве без потери данных

На самом деле я хотел бы использовать новый persistence.xml и производственная база данных, чтобы иметь возможность генерировать «дельту» между старой базой данных и новой.Я хотел бы иметь возможность получить код SQL, который выполняется, когда hbm2ddl находится в режиме «обновления».

Этот код 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 с модулем персистентности вне сервера приложений (настройки базы данных установлены на ресурсе JNDI в Glassfish).(попробовал, но он просто не может найти базу данных)

Я пробовал также с <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?(А что бы вы еще сделали, если бы не записывали все изменения БД в рукописные SQL-файлы?)
Это было полезно?

Решение

У Hbm2ddl есть API, который вы можете вызвать самостоятельно.Если существующие задачи ant не выполняют то, что вы хотите, вы всегда можете выполнить вызовы hbm2ddl самостоятельно, возможно, даже передав hibernate перегруженный драйвер jdbc, который регистрирует операторы выполнения, а не фактически выполняет их или перегружает методы выполнения hbm2ddl.

Я бы также добавил, что вам следует рассмотреть возможность использования Liquibase и создания XML-файлов вручную с использованием любых различий.Вы понимаете, что вам нужно будет проверить правильность сгенерированного SQL-запроса, его так же легко создавать шаг за шагом по мере разработки, и тогда вы ЗНАЕТЕ, что это правильно.

Мы используем спящий режим, и вместо использования интеграции спящего режима liquibase мы обновляем наши сопоставления спящего режима, запускаем интеграционные тесты, чтобы увидеть, что они терпят неудачу, создаем необходимый набор изменений liquibase (добавляем таблицу, добавляем столбец, переименовываем столбец и т. д.), а затем переименовываем -запустите тесты и посмотрите, как они пройдут.Создание журналов изменений шаг за шагом хорошо работает в обычном ритме разработки, не прибегая к использованию различий для чего-либо, кроме проверки работоспособности.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top