db迁移 - Hibernate / JPA - hbm2ddl - diff工具 [英] Db migrate - Hibernate/JPA - hbm2ddl - diff tools

查看:146
本文介绍了db迁移 - Hibernate / JPA - hbm2ddl - diff工具的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述




  • EJB3 / JPA(Hibernate)

  • MySQL 5
  • >


我必须设置一个系统来帮助数据库迁移。尝试使用LiquiBase,但它似乎还不够成熟,但与Hibernate一起使用。



我想要做的是:




  • 我在生产中使用了1.0版本的应用程序
  • 我开发并测试了应用程序的2.0版本

  • 我想在生产环境中更新应用程序数据库而不会丢失数据



其实我想用新的 persistence.xml ,生产数据库可以生成旧数据库和新数据库之间的增量。我希望能够检索当hbm2ddl处于更新模式时执行的SQL代码。



这个SQL代码将被修改(drop + create = rename等等),以避免丢失可能发生在 hbm2ddl.auto = update 上的数据。



是可能的,因为Hibernate在使用 hbm2ddl.auto = update 部署新版本时执行此操作。但我希望能够在 hibernatetool 的Ant任务中完成它。



我没有找到很多关于这个在互联网上的信息,所以我想知道如果有人已经做了这样的事情,并可以帮助我。



我已经做了以下:

 < hibernatetool destdir =$ {dist}> 
<! -
< jdbcconfiguration propertyfile =hibtest.properties>< / jdbcconfiguration>
- >
< jpaconfiguration persistenceunit =server-pu/>
< classpath>
< fileset dir =$ {core.lib.server}includes =*。jar/>
< fileset dir =$ {core.lib.build}includes =*。jar/>
< pathelement location =$ {core.class}/>
< pathelement location =$ {core.etc}/>
< / classpath>
export =falseupdate =true/>
< / hibernatetool>

我真的不知道该怎么做,我能够获得创建的sql文件,但我只想要三角洲。
我必须把更新=真?
我可以在应用程序服务器之外使用持久性单元的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:在org.hibernate.tool.ant.HibernateToolTask​​.reportException获取数据库元数据
(HibernateToolTask​​.java:226)$ or $ $ b $ org.hibernate.tool .ant.HibernateToolTask​​.execute(HibernateToolTask​​.java:189)
在org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:288)
在sun.reflect.GeneratedMethodAccessor1.invoke(未知
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)
在org.eclipse.ant.internal.ui.antsupport.InternalAntRunner.run(InternalAntRunner.java:423)
在org.eclipse.ant.internal.ui .antsupport.InternalAntRunner.main(InternalAntRunner.java:137)
原因:org.hibernate.exception.JDBCConnectionException:获取数据库在org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)元数据

。在org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getMetaData(AbstractMetaDataDialect.java:64)
。在org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.caseForSearch(AbstractMetaDataDialect.java:163)
在org.hibernate.cfg.reveng.dialect.JDBCMetaDataDialect.getTables(JDBCMetaDataDialect.java:22)
。在org.hibernate.cfg.reveng.JDBCReader.processTables(JDBCReader.java:476)维持在组织org.hibernate.cfg.reveng.JDBCReader.readDatabaseSchema(JDBCReader.java:74)

。 hibernate.cfg.reveng.JDBCReader.readDatabaseSchema(JDBCReader.java:860)
处org.hibernate.cfg.JDBCBinder org.hibernate.cfg.JDBCBinder.readDatabaseSchema(JDBCBinder.java:115)
。 readFromDatabase(JDBCBinder.java:88)
at org.hibernate.cfg.JDBCMetaDataConfiguration.readFromJDBC(JDBCMetaDataConfiguration.java:42)
at org.hibernate.tool.ant.JDBCConfig urationTask.doConfiguration(JDBCConfigurationTask.java:81)
在org.hibernate.tool.ant.ConfigurationTask.getConfiguration(ConfigurationTask.java:55)
在org.hibernate.tool.ant.HibernateToolTask​​.getConfiguration( HibernateToolTask​​.java:302)美元,org.hibernate.tool.ant.Hbm2DDLExporterTask.createExporter(Hbm2DDLExporterTask.java:51 b $ b)
在org.hibernate.tool.ant.ExporterTask.execute(ExporterTask.java: 39)
在org.hibernate.tool.ant.HibernateToolTask​​.execute(HibernateToolTask​​.java:186)
... 15 more
导致:java.sql.SQLException:没有合适的驱动程序找到的jdbc:mysql:3306 // localhost / db $ b $在java.sql.DriverManager.getConnection(DriverManager.java:602)
在java.sql.DriverManager.getConnection(DriverManager.java:154)
at org.hibernate.connection.DriverManagerConnectionProvider.getConnection(DriverManagerConnectionProvider.java:133)
at org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getConnection(Abstrac tMetaDataDialect.java:122)
在org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.getMetaData(AbstractMetaDataDialect.java:61)
... 29 more
---嵌套异常 - -
org.hibernate.exception.JDBCConnectionException:在org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:97)中获取数据库元数据
$ or $ $ $ org.hibernate.cfg.reveng .dialect.AbstractMetaDataDialect.getMetaData(AbstractMetaDataDialect.java:64)
在org.hibernate.cfg.reveng.dialect.AbstractMetaDataDialect.caseForSearch(AbstractMetaDataDialect.java:163)
在org.hibernate.cfg.reveng .dialect.JDBCMetaDataDialect.getTables(JDBCMetaDataDialect.java:22)
在org.hibernate.cfg.reveng.JDBCReader.processTables(JDBCReader.java:476)
在org.hibernate.cfg.reveng.JDBCReader .readDatabaseSchema(JDBCReader.java:74)
at org.hibernate.cfg.reveng.JDBCReader.readDatabaseSchema(JDBCReader.java:860)
at org.hibernate.cfg.JDBCBinder.readD atabaseSchema(JDBCBinder.java:115)
在org.hibernate.cfg.JDBCBinder.readFromDatabase(JDBCBinder.java:88)
在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)
在org.hibernate.tool.ant.HibernateToolTask​​.getConfiguration(HibernateToolTask​​.java:302)
在org.hibernate.tool.ant.Hbm2DDLExporterTask.createExporter(Hbm2DDLExporterTask.java:51)
在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(Deleg atingMethodAccessorImpl.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)
在org.apache.tools.ant.Target.performTasks(Target.java:385)
在org.apache.tools.ant.Project.executeSortedTargets(Project.java:1329)
在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)
导致:java.sql.SQLException:找不到适合jdbc的驱动程序:mysql:3306 // localhost / db $ b $ 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)
在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.pas sword = 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 / serverincludes =*。jar/>

我也将它添加到Ant(Eclipse插件)的运行配置类路径中。



所以我的问题是:


  • 我做错了什么事来做我想做的事?

  • 这是你将使用Hibernate框架进行数据库迁移的方式吗? (如果不是在手工制作的SQL文件中编写所有数据库更改,您还会做什么?)

解决方案

Hbm2ddl确实有一个你可以自己调用的API。如果现有的ant任务没有做到你想做的事,你总是可以自己做hbm2ddl调用,甚至可能通过hibernate传递一个重载的jdbc驱动程序来记录执行语句,而不是实际执行它们或重载hbm2ddl执行方法。



我还会补充一点,您应该查看使用liquibase并通过任何差异手动创建xml文件。您知道您需要验证生成的sql是否正确,在开发时一次只创建一个步骤就很容易,然后您知道它是正确的。



我们使用hibernate,而不是使用liquibase hibernate集成,我们更新我们的hibernate映射,运行我们的集成测试以查看它们失败,创建必要的liquibase变更集(添加表,添加列,重命名列等),然后重新运行测试并看到它们通过。逐步建立更新日志可以和正常的开发节奏一起工作,而不需要区分除了完整性检查之外的任何事情。

I use:

  • EJB3 / JPA (Hibernate)
  • MySQL 5

I have to set up a system to help database migrations. Tried to use LiquiBase but it seems not enough mature yet to be used with Hibernate.

What I would like to do is:

  • I have version 1.0 of the application in production
  • I have version 2.0 of the application developed and tested
  • I want to update the application database in production without losing data

Actually I would like to use the new persistence.xml and the production database to be able to generate the "delta" between the old database and the new. I would like to be able to retrieve the SQL code that is executed when hbm2ddl is on "update" mode.

This SQL code will be modified (drop+create=rename etc...) to avoid losing data that could happen with hbm2ddl.auto=update.

I guess it is possible because Hibernate does it when deploying a new version with hbm2ddl.auto=update. But I want to be able to do it in an Ant task with hibernatetool.

I don't find many informations about this on internet so i wonder if someone already done something like that here and could help me.

I've done the following:

<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>

I don't really know how to do, i was able to get the creation sql file, but i just want the delta. I have to put update="true" ? Can i use the jpaconfig with persistence unit outside of application server (the db settings are set on JNDI ressource on Glassfish). (tried and it just can't find the db)

I tried also with <jdbcconfiguration propertyfile="hibtest.properties"></jdbcconfiguration> or setting properties of the database in persistence.xml instead of using JNDI resource.

I got the following error:

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

I use MySQL, and my JDBC properties are:

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

My JDBC MySQL driver is in ${core.lib.server}: mysql-connector-java-5.1.7-bin.jar. (I also tried to put in classpath <fileset dir="/home/slorber/workspace/core/lib/server" includes="*.jar" />.)

I also added it to the run configuration classpath of Ant (Eclipse plugin).

So my questions are:

  • Have I done something wrong to do what I want?
  • Is this the way you would do a db migrate with a Hibernate framework? (And what else would you do if not writing all db changes in hand-made SQL files?)

解决方案

Hbm2ddl does have an API you can call on your own. If the existing ant tasks aren't doing what you want, you can always make the hbm2ddl calls yourself, possibly even passing hibernate an overloaded jdbc driver that logs execute statements rather than actually executing them or overloading the hbm2ddl execute methods.

I would also add that you should look at using liquibase and creating xml files manually over any sort of diffs. You recognize that you will need to validate that the generated sql is correct, it is just as easy to create it one step at a time as you develop, and then you KNOW it is right.

We use hibernate, and rather than using the liquibase hibernate integration, we update our hibernate mappings, run our integration tests to see that they fail, create the necessary liquibase changeset (add table, add column, rename column, etc.), then re-run the tests and see them pass. Building up the changelogs step by step works well with the regular rhythm of development without resorting to diffs for anything beyond sanity checks.

这篇关于db迁移 - Hibernate / JPA - hbm2ddl - diff工具的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆