问题
As described here (https://github.com/liquibase/liquibase-hibernate/issues/74) I'm having an issue getting the liquibase-hibernate extension to work properly. I think I have everything setup, but it seems like I keep running into weird problems. I feel like I'm missing something simple, but I think I've followed all the instructions as provided.
I'm using liquibase 3.3.2, Hibernate 4.3.0.Final, java 1.7.0_71 and the liquibase-hibernate4-3.5.jar. My CLASSPATH environmental variable is empty, but some stuff gets added to it by the liquibase shell script. When I'm using normal liquibase commands interacting, and I remove the extension from $LIQUIBASE_HOME/lib/ directory without the extension it works just fine. I reran the commands with DEBUG output on to provide some more information.
$ echo $CLASSPATH
$ java -version
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)
$ liquibase --version
Liquibase Version: 3.3.2
$ liquibase diffChangeLog
//The below is the stuff liquibase is adding to my classpath
.:/c/repos/ServeDirtyLibsInJava/liquibaseLib/liquibase.jar:/c/repos/ServeDirtyLibsInJava/liquibaseLib/lib/liquibase-hibernate4-3.5.jar:/c/repos/ServeDirtyLibsInJava/liquibaseLib/lib/snakeyaml-1.13.jar
WARNING 1/19/15 12:42 AM: liquibase: Can not use class liquibase.ext.hibernate.database.HibernateEjb3Database as a Liquibase service because org.hibernate.dialect.Dialect is not in the classpath
WARNING 1/19/15 12:42 AM: liquibase: Can not use class liquibase.ext.hibernate.database.HibernateSpringDatabase as a Liquibase service because org.hibernate.dialect.Dialect is not in the classpath
WARNING 1/19/15 12:42 AM: liquibase: Can not use class liquibase.ext.hibernate.database.HibernateClassicDatabase as a Liquibase service because org.hibernate.dialect.Dialect is not in the classpath
DEBUG 1/19/15 10:20 AM: liquibase: Connected to root@localhost@jdbc:mysql://localhost:3306/dirtylibs
DEBUG 1/19/15 10:20 AM: liquibase: Setting auto commit to false from true
Unexpected error running Liquibase: java.lang.RuntimeException: Cannot find database driver: Driver class was not specified and could not be determined from the url (hibernate:spring:com.companyname.dirtylibs.persistence.entities?dialect=org.hibernate.dialect.MySQL5Dialect)
SEVERE 1/19/15 10:20 AM: liquibase: java.lang.RuntimeException: Cannot find database driver: Driver class was not specified and could not be determined from the url (hibernate:spring:com.companyname.dirtylibs.persistence.entities?dialect=org.hibernate.dialect.MySQL5Dialect)
liquibase.exception.DatabaseException: liquibase.exception.DatabaseException: java.lang.RuntimeException: Cannot find database driver: Driver class was not specified and could not be determined from the url (hibernate:spring:com.companyname.dirtylibs.persistence.entities?dialect=org.hibernate.dialec
t.MySQL5Dialect)
at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:69)
at liquibase.integration.commandline.Main.createReferenceDatabaseFromCommandParams(Main.java:1169)
at liquibase.integration.commandline.Main.doMigration(Main.java:936)
at liquibase.integration.commandline.Main.run(Main.java:175)
at liquibase.integration.commandline.Main.main(Main.java:94)
Caused by: liquibase.exception.DatabaseException: java.lang.RuntimeException: Cannot find database driver: Driver class was not specified and could not be determined from the url (hibernate:spring:com.companyname.dirtylibs.persistence.entities?dialect=org.hibernate.dialect.MySQL5Dialect)
at liquibase.database.DatabaseFactory.openConnection(DatabaseFactory.java:239)
at liquibase.database.DatabaseFactory.openDatabase(DatabaseFactory.java:143)
at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:50)
... 4 more
Caused by: java.lang.RuntimeException: Cannot find database driver: Driver class was not specified and could not be determined from the url (hibernate:spring:com.companyname.dirtylibs.persistence.entities?dialect=org.hibernate.dialect.MySQL5Dialect)
at liquibase.database.DatabaseFactory.openConnection(DatabaseFactory.java:191)
... 6 more
My liquibase.properties file
driver=com.mysql.jdbc.Driver
classpath=mysql-connector-java-5.1.6.jar
url=jdbc:mysql://localhost:3306/dirtylibs
username=root
password=password
changeLogFile=changelog.xml
#referenceDriver=liquibase.ext.hibernate.database.connection.HibernateDriver
referenceUrl=hibernate:spring:com.companyname.dirtylibs.persistence.entities?dialect=org.hibernate.dialect.MySQL5Dialect
referenceUsername=root
referencePassword=password
If I uncomment my referenceDriver I get this. Is there something I'm missing here? I thought I had all the required dependencies, and I'm not sure if this is some manifestation of the earlier problem where the extension could not load stuff properly.
$ liquibase diffChangeLog
WARNING 1/19/15 12:49 AM: liquibase: Can not use class liquibase.ext.hibernate.database.HibernateEjb3Database as a Liquibase service because org.hibernate.dialect.Dialect is not in the classpath
WARNING 1/19/15 12:49 AM: liquibase: Can not use class liquibase.ext.hibernate.database.HibernateSpringDatabase as a Liquibase service because org.hibernate.dialect.Dialect is not in the classpath
WARNING 1/19/15 12:49 AM: liquibase: Can not use class liquibase.ext.hibernate.database.HibernateClassicDatabase as a Liquibase service because org.hibernate.dialect.Dialect is not in the classpath
WARNING 1/19/15 12:49 AM: liquibase: Can not use class liquibase.ext.hibernate.snapshot.SequenceSnapshotGenerator as a Liquibase service because org.hibernate.id.factory.IdentifierGeneratorFactory is not in the classpath
WARNING 1/19/15 12:49 AM: liquibase: Can not use class liquibase.ext.hibernate.snapshot.TableSnapshotGenerator as a Liquibase service because org.hibernate.id.factory.IdentifierGeneratorFactory is not in the classpath
Unexpected error running Liquibase: org.hibernate.sql.Alias
SEVERE 1/19/15 10:22 AM: liquibase: org.hibernate.sql.Alias
java.lang.NoClassDefFoundError: org/hibernate/sql/Alias
at liquibase.ext.hibernate.snapshot.PrimaryKeySnapshotGenerator.<clinit>(PrimaryKeySnapshotGenerator.java:27)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:57)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
at liquibase.snapshot.SnapshotGeneratorFactory.<init>(SnapshotGeneratorFactory.java:29)
at liquibase.snapshot.SnapshotGeneratorFactory.getInstance(SnapshotGeneratorFactory.java:43)
at liquibase.snapshot.SnapshotControl.addType(SnapshotControl.java:95)
at liquibase.snapshot.SnapshotControl.setTypes(SnapshotControl.java:88)
at liquibase.snapshot.SnapshotControl.<init>(SnapshotControl.java:25)
at liquibase.command.DiffCommand.createReferenceSnapshot(DiffCommand.java:185)
at liquibase.command.DiffCommand.createDiffResult(DiffCommand.java:140)
at liquibase.command.DiffToChangeLogCommand.run(DiffToChangeLogCommand.java:51)
at liquibase.command.AbstractCommand.execute(AbstractCommand.java:8)
at liquibase.integration.commandline.CommandLineUtils.doDiffToChangeLog(CommandLineUtils.java:121)
at liquibase.integration.commandline.Main.doMigration(Main.java:936)
at liquibase.integration.commandline.Main.run(Main.java:175)
at liquibase.integration.commandline.Main.main(Main.java:94)
Caused by: java.lang.ClassNotFoundException: org.hibernate.sql.Alias
at java.net.URLClassLoader$1.run(URLClassLoader.java:366)
at java.net.URLClassLoader$1.run(URLClassLoader.java:355)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:354)
at java.lang.ClassLoader.loadClass(ClassLoader.java:425)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:308)
at java.lang.ClassLoader.loadClass(ClassLoader.java:358)
... 18 more
After adding the hibernate jar to the liquibase/lib folder (which is really wrong) the error turned into this. I tried reverting to an older version of the plugin (while downgrading liquibase as well), and it did not help.
$ liquibase --logLevel=DEBUG diffChangeLog
.:/c/repos/ServeDirtyLibsInJava/liquibaseLib/liquibase.jar:/c/repos/ServeDirtyLibsInJava/liquibaseLib/lib/hibernate-core-4.3.0.Final.jar:/c/repos/ServeDirtyLibsInJava/liquibaseLib/lib/liquibase-hibernate4-3.5.jar:/c/repos/ServeDirtyLibsInJava/liquibaseLib/lib/snakeyaml-1.13.jar
WARNING 1/19/15 10:38 AM: liquibase: Can not use class liquibase.ext.hibernate.database.HibernateSpringDatabase as a Liquibase service because org.springframework.beans.factory.support.BeanDefinitionRegistry is not in the classpath
DEBUG 1/19/15 10:38 AM: liquibase: Connected to root@localhost@jdbc:mysql://localhost:3306/dirtylibs
DEBUG 1/19/15 10:38 AM: liquibase: Setting auto commit to false from true
WARNING 1/19/15 10:38 AM: liquibase: Unknown database: Hibernate
DEBUG 1/19/15 10:38 AM: liquibase: Connected to null@hibernate:spring:com.companyname.dirtylibs.persistence.entities?dialect=org.hibernate.dialect.MySQL5Dialect
DEBUG 1/19/15 10:38 AM: liquibase: Not adjusting the auto commit mode; it is already false
INFO 1/19/15 10:38 AM: liquibase: Error getting default schema
java.lang.NullPointerException
at liquibase.executor.jvm.JdbcExecutor$QueryCallableStatementCallback.doInCallableStatement(JdbcExecutor.java:383)
at liquibase.executor.jvm.JdbcExecutor.execute(JdbcExecutor.java:96)
at liquibase.executor.jvm.JdbcExecutor.query(JdbcExecutor.java:132)
at liquibase.executor.jvm.JdbcExecutor.query(JdbcExecutor.java:143)
at liquibase.executor.jvm.JdbcExecutor.queryForObject(JdbcExecutor.java:151)
at liquibase.executor.jvm.JdbcExecutor.queryForObject(JdbcExecutor.java:166)
at liquibase.executor.jvm.JdbcExecutor.queryForObject(JdbcExecutor.java:161)
at liquibase.database.AbstractJdbcDatabase.getConnectionSchemaName(AbstractJdbcDatabase.java:318)
at liquibase.database.AbstractJdbcDatabase.getDefaultSchemaName(AbstractJdbcDatabase.java:301)
at liquibase.CatalogAndSchema.customize(CatalogAndSchema.java:132)
at liquibase.snapshot.SnapshotGeneratorFactory.createSnapshot(SnapshotGeneratorFactory.java:116)
at liquibase.command.DiffCommand.createReferenceSnapshot(DiffCommand.java:190)
at liquibase.command.DiffCommand.createDiffResult(DiffCommand.java:140)
at liquibase.command.DiffToChangeLogCommand.run(DiffToChangeLogCommand.java:51)
at liquibase.command.AbstractCommand.execute(AbstractCommand.java:8)
at liquibase.integration.commandline.CommandLineUtils.doDiffToChangeLog(CommandLineUtils.java:121)
at liquibase.integration.commandline.Main.doMigration(Main.java:936)
at liquibase.integration.commandline.Main.run(Main.java:175)
at liquibase.integration.commandline.Main.main(Main.java:94)
DEBUG 1/19/15 10:38 AM: liquibase: Computed checksum for 1421681927678 as b60efdd1567f2fd4e5407a8d157cb0b6
Unexpected error running Liquibase: java.lang.NullPointerException
SEVERE 1/19/15 10:38 AM: liquibase: java.lang.NullPointerException
liquibase.exception.LiquibaseException: liquibase.command.CommandExecutionException: java.lang.NullPointerException
at liquibase.integration.commandline.CommandLineUtils.doDiffToChangeLog(CommandLineUtils.java:123)
at liquibase.integration.commandline.Main.doMigration(Main.java:936)
at liquibase.integration.commandline.Main.run(Main.java:175)
at liquibase.integration.commandline.Main.main(Main.java:94)
Caused by: liquibase.command.CommandExecutionException: java.lang.NullPointerException
at liquibase.command.AbstractCommand.execute(AbstractCommand.java:13)
at liquibase.integration.commandline.CommandLineUtils.doDiffToChangeLog(CommandLineUtils.java:121)
... 3 more
Caused by: java.lang.NullPointerException
at liquibase.snapshot.jvm.CatalogSnapshotGenerator.getDatabaseCatalogNames(CatalogSnapshotGenerator.java:82)
at liquibase.snapshot.jvm.CatalogSnapshotGenerator.snapshotObject(CatalogSnapshotGenerator.java:41)
at liquibase.snapshot.jvm.JdbcSnapshotGenerator.snapshot(JdbcSnapshotGenerator.java:60)
at liquibase.snapshot.SnapshotGeneratorChain.snapshot(SnapshotGeneratorChain.java:50)
at liquibase.snapshot.DatabaseSnapshot.include(DatabaseSnapshot.java:163)
at liquibase.snapshot.DatabaseSnapshot.init(DatabaseSnapshot.java:55)
at liquibase.snapshot.DatabaseSnapshot.<init>(DatabaseSnapshot.java:37)
at liquibase.snapshot.JdbcDatabaseSnapshot.<init>(JdbcDatabaseSnapshot.java:25)
at liquibase.snapshot.SnapshotGeneratorFactory.createSnapshot(SnapshotGeneratorFactory.java:126)
at liquibase.snapshot.SnapshotGeneratorFactory.createSnapshot(SnapshotGeneratorFactory.java:119)
at liquibase.command.DiffCommand.createReferenceSnapshot(DiffCommand.java:190)
at liquibase.command.DiffCommand.createDiffResult(DiffCommand.java:140)
at liquibase.command.DiffToChangeLogCommand.run(DiffToChangeLogCommand.java:51)
at liquibase.command.AbstractCommand.execute(AbstractCommand.java:8)
... 4 more
回答1:
I got it working by adding these jars to my classpath. This is super confusing and not well documented. The process I went through was:
Download the source for the correct plugin project found here (https://github.com/liquibase/liquibase-hibernate/releases) in my case it was liquibase-hibernate4-3.5.
Run
mvn dependency:copy-dependencies
. This dumps them into/target/dependency/
. Copy all these jars and put them into yourLIQUIBASE_HOME/lib
directory.I'm using gradle so I used a custom task to copy all my dependencies. If you're using maven you can use the same step from 2 on your own project to fetch all your depdenencies. I copied these libs from my output directory into the
LIQUIBASE_HOME/lib
directory.task copyToLib(type: Copy) { into "$buildDir/output/libs" from configurations.runtime }
I also put the correct
hibernate-liquibase-4.3.5.jar
into theLIQUIBASE_HOME/lib
directory.
That gave me all the dependencies I needed for the plugin.
This is a big nasty ball of mess, but what can you do :(
回答2:
If you check the source code for this plugin, the following dependencies (all the spring dependencies) are marked as "provided" scope in the pom:
spring-test
spring-jdbc
spring-beans
spring-context
spring-orm
So the plugin will assume these have been provided on the classpath by your app, but this won't automatically happen in your maven build, as it will not run with the same classpath that your application will.
So, to fix, add the dependencies in your plugin, easier than doing the jar file shuffle:
<plugin>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-maven-plugin</artifactId>
<version>3.4.1</version>
<dependencies>
<dependency>
<groupId>org.liquibase.ext</groupId>
<artifactId>liquibase-hibernate5</artifactId>
<version>3.6</version>
</dependency>
<dependency>
<groupId>org.liquibase</groupId>
<artifactId>liquibase-core</artifactId>
<version>3.5.3</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-beans</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>4.3.2.RELEASE</version>
</dependency>
</dependencies>
</plugin>
If you are keen, you can do a pull request on the github repo to remove the provided scopes from the pom, oh and probably this line too:
<role>architect</role>
回答3:
The path I tried was a bit different with the accepted anwer. I created a dev profile in my war's pom.xml (I am using maven) which does exactly the same with the default profile but including the Liquibase-hibernate dependency jar files under the war/WEB-INF/lib. And then instead of using the liquibase command line provided, I use the liquibase.jar file directly with the classpath is my war file:
java -jar $LIQUIBASE/liquibase.jar --classpath=<WAR FILE HERE> --defaultsFile=<yourpath>/liquibase.properties --logLevel=info
And then created a connvenience script which will build my project with that liquibase-hibernate profile then execute the diffChangeLog command.
回答4:
I got the same error. I fixed it by removing the hbm2ddl-property in the hibernate.cfg.xml. Somehow the driver class cannot be read in the cfg.xml if this property is on. There is a part in the liquibase-hibernate wiki in git where it says "Why not to use HBM2DDL" but it does not really say to remove it from the cfg.xml.
来源:https://stackoverflow.com/questions/28029556/liquibase-hibernate-plugin-does-not-work