在构建时自动更新Liquibase的更改日志

时间:2015-06-22 05:37:33

标签: java spring hibernate gradle liquibase

我目前正在开发一个使用Hibernate和Liquibase的Spring项目。我想要实现的是每次构建项目时自动更新Liquibase的更改日志。它应该基于我当前的高效数据库和我更新的Hibernate实体生成差异。

但我遇到的问题是每次清理和重建项目时都会出现以下错误:

liquibase-plugin: Running the 'main' activity...
INFO 6/22/15 11:12 AM: liquibase-hibernate: Reading hibernate configuration hibernate:spring:com.example.name.domain?dialect=org.hibernate.dialect.MySQL5Dialect
INFO 6/22/15 11:12 AM: liquibase-hibernate: Found package com.example.app.domain
INFO 6/22/15 11:12 AM: liquibase-hibernate: Found dialect org.hibernate.dialect.MySQL5Dialect
Unexpected error running Liquibase: Unable to resolve persistence unit root URL

SEVERE 6/22/15 11:12 AM: liquibase: Unable to resolve persistence unit root URL
liquibase.exception.DatabaseException: javax.persistence.PersistenceException: Unable to resolve persistence unit root URL
        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 sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
        at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.invoke(StaticMetaMethodSite.java:43)
        at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.call(StaticMetaMethodSite.java:88)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
        at org.liquibase.gradle.LiquibaseTask.runLiquibase(LiquibaseTask.groovy:97)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:382)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015)
        at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:66)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
        at org.liquibase.gradle.LiquibaseTask$_liquibaseAction_closure1.doCall(LiquibaseTask.groovy:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:292)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015)
        at groovy.lang.Closure.call(Closure.java:423)
        at groovy.lang.Closure.call(Closure.java:439)
        at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1379)
        at org.codehaus.groovy.runtime.DefaultGroovyMethods.each(DefaultGroovyMethods.java:1310)
        at org.codehaus.groovy.runtime.dgm$150.invoke(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:271)
        at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:53)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
        at org.liquibase.gradle.LiquibaseTask.liquibaseAction(LiquibaseTask.groovy:46)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:75)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.doExecute(AnnotationProcessingTaskFactory.java:226)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:219)
        at org.gradle.api.internal.project.taskfactory.AnnotationProcessingTaskFactory$StandardTaskAction.execute(AnnotationProcessingTaskFactory.java:208)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:589)
        at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:572)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310)
        at org.gradle.api.internal.AbstractTask.execute(AbstractTask.java:305)
        at org.gradle.api.internal.TaskInternal$execute$0.call(Unknown Source)
        at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
        at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:112)
        at build_au43cnsvyw2rwctsxb5mg4cmw$_run_closure4.doCall(/Users/mihajlovic/Documents/repos/Backend/dbmigration/build.gradle:52)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
        at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:324)
        at org.codehaus.groovy.runtime.metaclass.ClosureMetaClass.invokeMethod(ClosureMetaClass.java:292)
        at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1015)
        at groovy.lang.Closure.call(Closure.java:423)
        at groovy.lang.Closure.call(Closure.java:439)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:558)
        at org.gradle.api.internal.AbstractTask$ClosureTaskAction.execute(AbstractTask.java:539)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:77)
        at org.gradle.api.internal.tasks.TaskMutator$1.execute(TaskMutator.java:73)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:80)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:61)
        at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:46)
        at org.gradle.api.internal.tasks.execution.PostExecutionAnalysisTaskExecuter.execute(PostExecutionAnalysisTaskExecuter.java:35)
        at org.gradle.api.internal.tasks.execution.SkipUpToDateTaskExecuter.execute(SkipUpToDateTaskExecuter.java:64)
        at org.gradle.api.internal.tasks.execution.ValidatingTaskExecuter.execute(ValidatingTaskExecuter.java:58)
        at org.gradle.api.internal.tasks.execution.SkipEmptySourceFilesTaskExecuter.execute(SkipEmptySourceFilesTaskExecuter.java:42)
        at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:52)
        at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:53)
        at org.gradle.api.internal.tasks.execution.ExecuteAtMostOnceTaskExecuter.execute(ExecuteAtMostOnceTaskExecuter.java:43)
        at org.gradle.api.internal.AbstractTask.executeWithoutThrowingTaskFailure(AbstractTask.java:310)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.executeTask(AbstractTaskPlanExecutor.java:79)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.processTask(AbstractTaskPlanExecutor.java:63)
        at org.gradle.execution.taskgraph.AbstractTaskPlanExecutor$TaskExecutorWorker.run(AbstractTaskPlanExecutor.java:51)
        at org.gradle.execution.taskgraph.DefaultTaskPlanExecutor.process(DefaultTaskPlanExecutor.java:23)
        at org.gradle.execution.taskgraph.DefaultTaskGraphExecuter.execute(DefaultTaskGraphExecuter.java:88)
        at org.gradle.execution.SelectedTaskExecutionAction.execute(SelectedTaskExecutionAction.java:37)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
        at org.gradle.execution.DefaultBuildExecuter.access$200(DefaultBuildExecuter.java:23)
        at org.gradle.execution.DefaultBuildExecuter$2.proceed(DefaultBuildExecuter.java:68)
        at org.gradle.execution.DryRunBuildExecutionAction.execute(DryRunBuildExecutionAction.java:32)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:62)
        at org.gradle.execution.DefaultBuildExecuter.execute(DefaultBuildExecuter.java:55)
        at org.gradle.initialization.DefaultGradleLauncher.doBuildStages(DefaultGradleLauncher.java:149)
        at org.gradle.initialization.DefaultGradleLauncher.doBuild(DefaultGradleLauncher.java:106)
        at org.gradle.initialization.DefaultGradleLauncher.run(DefaultGradleLauncher.java:86)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter$DefaultBuildController.run(InProcessBuildActionExecuter.java:90)
        at org.gradle.tooling.internal.provider.ExecuteBuildActionRunner.run(ExecuteBuildActionRunner.java:28)
        at org.gradle.launcher.exec.ChainingBuildActionRunner.run(ChainingBuildActionRunner.java:35)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:41)
        at org.gradle.launcher.exec.InProcessBuildActionExecuter.execute(InProcessBuildActionExecuter.java:28)
        at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:50)
        at org.gradle.launcher.exec.DaemonUsageSuggestingBuildActionExecuter.execute(DaemonUsageSuggestingBuildActionExecuter.java:27)
        at org.gradle.launcher.cli.RunBuildAction.run(RunBuildAction.java:40)
        at org.gradle.internal.Actions$RunnableActionAdapter.execute(Actions.java:169)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:237)
        at org.gradle.launcher.cli.CommandLineActionFactory$ParseAndBuildAction.execute(CommandLineActionFactory.java:210)
        at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:35)
        at org.gradle.launcher.cli.JavaRuntimeValidationAction.execute(JavaRuntimeValidationAction.java:24)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:206)
        at org.gradle.launcher.cli.CommandLineActionFactory$WithLogging.execute(CommandLineActionFactory.java:169)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:33)
        at org.gradle.launcher.cli.ExceptionReportingAction.execute(ExceptionReportingAction.java:22)
        at org.gradle.launcher.Main.doAction(Main.java:33)
        at org.gradle.launcher.bootstrap.EntryPoint.run(EntryPoint.java:45)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:497)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.runNoExit(ProcessBootstrap.java:54)
        at org.gradle.launcher.bootstrap.ProcessBootstrap.run(ProcessBootstrap.java:35)
        at org.gradle.launcher.GradleMain.main(GradleMain.java:23)
Caused by: javax.persistence.PersistenceException: Unable to resolve persistence unit root URL
        at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:580)
        at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.preparePersistenceUnitInfos(DefaultPersistenceUnitManager.java:436)
        at liquibase.ext.hibernate.database.HibernateSpringDatabase.buildConfigurationFromScanning(HibernateSpringDatabase.java:227)
        at liquibase.ext.hibernate.database.HibernateSpringDatabase.buildConfiguration(HibernateSpringDatabase.java:55)
        at liquibase.ext.hibernate.database.HibernateDatabase.setConnection(HibernateDatabase.java:45)
        at liquibase.database.DatabaseFactory.findCorrectDatabaseImplementation(DatabaseFactory.java:123)
        at liquibase.database.DatabaseFactory.openDatabase(DatabaseFactory.java:143)
        at liquibase.integration.commandline.CommandLineUtils.createDatabaseObject(CommandLineUtils.java:50)
        ... 140 more
Caused by: java.io.FileNotFoundException: class path resource [] cannot be resolved to URL because it does not exist
        at org.springframework.core.io.ClassPathResource.getURL(ClassPathResource.java:187)
        at org.springframework.orm.jpa.persistenceunit.DefaultPersistenceUnitManager.determineDefaultPersistenceUnitRootUrl(DefaultPersistenceUnitManager.java:577)
        ... 147 more

据我所知,问题是Liquibase需要将所有实体类加载到gradle的类路径中,但由于Java类只是被编译或者尚未编译,但事实并非如此,因此错误消息。

我可以通过两个步骤构建项目来修复此错误:

  1. 首先,我执行任务compileJava来构建实体类。
  2. 一旦完成,我可以执行正常build - 现在没有任何问题。
  3. 然而,分两个步骤构建项目非常繁琐。有没有办法解决这个问题,只需一步即可构建它?

    我的build.gradle目前看起来像这样:

    buildscript {
        ext {
            springBootVersion = '1.2.3.RELEASE'
        }
        repositories {
            mavenCentral()
            files 'build/classes/main'
        }
        dependencies {
            classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
            classpath("io.spring.gradle:dependency-management-plugin:0.5.0.RELEASE")
            classpath("org.liquibase:liquibase-gradle-plugin:1.1.0")
            classpath("mysql:mysql-connector-java:5.1.35")
            classpath('org.hibernate.javax.persistence:hibernate-jpa-2.1-api:1.0.0.Final')
            classpath('org.liquibase.ext:liquibase-hibernate4:3.5')
            classpath('org.springframework.data:spring-data-jpa:1.8.0.RELEASE')
            classpath files('build/classes/main/')
    
        }
    }
    
    apply plugin: 'org.liquibase.gradle'
    apply plugin: 'java'
    apply plugin: 'eclipse-wtp'
    apply plugin: 'idea'
    apply plugin: 'spring-boot'
    apply plugin: 'io.spring.dependency-management'
    apply plugin: 'war'
    
    
    war {
        baseName = 'example'
        version = '0.0.1-SNAPSHOT'
    }
    sourceCompatibility = 1.8
    targetCompatibility = 1.8
    
    repositories {
        mavenCentral()
    
        flatDir {
            dirs 'libs'
        }
    }
    
    configurations {
        providedRuntime
    }
    
    dependencies {
        compile("org.springframework.boot:spring-boot-starter-data-jpa")
        compile("org.springframework.boot:spring-boot-starter-web")
        compile("org.apache.commons:commons-lang3:3.0")
        compile("mysql:mysql-connector-java:5.1.35")
        compile('org.liquibase:liquibase-core:3.3.5')
    
        providedRuntime("org.springframework.boot:spring-boot-starter-tomcat")
        testCompile("org.springframework.boot:spring-boot-starter-test")
    }
    
    liquibase {
        activities {
            main {
                changeLogFile 'src/main/resources/db/changelog/db.changelog-master.xml'
                url 'jdbc:mysql://localhost:3306/Example'
                username 'root'
                password ''
                referenceDriver 'liquibase.ext.hibernate.database.connection.HibernateDriver'
                referenceUrl 'hibernate:spring:com.example.app.domain?dialect=org.hibernate.dialect.MySQL5Dialect'
            }
        }
        runList = 'main'
    }
    
    
    
    eclipse {
        classpath {
            containers.remove('org.eclipse.jdt.launching.JRE_CONTAINER')
            containers 'org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.7'
        }
    }
    
    task wrapper(type: Wrapper) {
        gradleVersion = '2.4'
    }
    

2 个答案:

答案 0 :(得分:2)

我终于明白了!您可以使用Exec类型在命令行中执行命令,随后启动新进程。您可以在the documentation中找到更多信息。

这是我最终得到的解决方案:

task updateChangeLog(type: Exec) {
    commandLine 'gradle', 'diffChangeLog'
}
updateChangeLog.dependsOn compileJava

这将使用我的diffChangeLog任务启动一个新的单独gradle进程。

答案 1 :(得分:0)

您可以像这样定义Liquibase任务:

task liquibase(type: JavaExec, depends: build) { 
    classpath = sourceSets.main.runtimeClasspath ... 
}