【问题标题】:Unable to generate difference from liquibase gradle plugin无法与 liquibase gradle 插件生成差异
【发布时间】:2016-06-13 11:38:56
【问题描述】:

我正在尝试使用 MYSQL 数据库在现有 SpringBoot 项目中实现 liquibase。我希望能够生成更改集,指定实体更改时的差异。

我做了什么:

我在build.gradle 文件中添加了 liquibase 依赖项和 gradle liquibase 插件。更改域后,我运行了gradle generateChangeLog。命令执行成功,但没有任何反应。

我在某处读到这个 ​​gradle 插件仅适用于 inmemory h2 数据库?真的吗?如果是,那么我应该使用什么替代方法来自动生成变更日志。

我找不到一个基于 SpringBoot gradle 的工作示例,该示例使用 MYSQL 并具有 liquibase 实现的自动更改生成能力。如果有人能提供,那就太好了。

参考文献:

https://github.com/stevesaliman/liquibase-workshop

https://github.com/liquibase/liquibase-gradle-plugin

【问题讨论】:

    标签: mysql gradle spring-boot liquibase changeset


    【解决方案1】:

    注意。要将 Hazim 的出色答案应用于 Spring boot 2 referenceUrl 参数应该有 "&hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&hibernate.implicit_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringImplicitNamingStrategy"

    【讨论】:

      【解决方案2】:
      liquibase {
      activities {
          main {
              changeLogFile 'src/main/resources/liquibase-changeLog-db1.xml'
              classpath "$projectDir/src/main/resources"
              url props["database.db1.url"]
              referenceUrl props["database.db3.url"]
              username props["database.db1.user"]
              password props["database.db1.password"]
              referenceUsername props["database.db3.user"]
              referencePassword props["database.db3.password"]
      
          }
          secondary {
              changeLogFile 'src/main/resources/liquibase-changeLog-db2.xml'
              classpath "$projectDir/src/main/resources"
              url props["database.db2.url"]
              username props["database.db2.user"]
              password props["database.db2.password"]
          }
          tertiary {
              changeLogFile 'src/main/resources/liquibase-changeLog-db1.xml'
              classpath "$projectDir/src/main/resources"
              url props["database.db3.url"]
              username props["database.db3.user"]
              password props["database.db3.password"]
          }
          runList =  project.ext.runList
      }
      

      }

      在这里,当您运行命令./gradlew diff prunList=main 时,它将获取主数据库并将其与参考数据库进行比较,并以以下格式在控制台中打印出差异。您可能需要在 application.properties 文件中添加 db url 和密码。在我的 application.properties 文件中我已经定义了 3 个 dbs。在我的第一个和第三个中它们几乎相同,除了添加了一个小列。在下面的差异中,它已经确定了缺失的列。

      Compared Schemas: liquibase_new -> liquibase2
      Product Name: EQUAL
      Product Version: EQUAL
      Missing Catalog(s): NONE
      Unexpected Catalog(s): NONE
      Changed Catalog(s): NONE
      Missing Column(s):
           liquibase_new.business_center.new
      Unexpected Column(s):
           liquibase2.business_center.new_column
      Changed Column(s): NONE
      Missing Foreign Key(s): NONE
      Unexpected Foreign Key(s): NONE
      Changed Foreign Key(s): NONE
      Missing Index(s): NONE
      Unexpected Index(s): NONE
      Changed Index(s): NONE
      Missing Primary Key(s): NONE
      Unexpected Primary Key(s): NONE
      Changed Primary Key(s): NONE
      Missing Sequence(s): NONE
      Unexpected Sequence(s): NONE
      Changed Sequence(s): NONE
      Missing Table(s): NONE
      Unexpected Table(s): NONE
      Changed Table(s): NONE
      Missing Unique Constraint(s): NONE
      Unexpected Unique Constraint(s): NONE
      Changed Unique Constraint(s): NONE
      Missing View(s): NONE
      Unexpected View(s): NONE
      Changed View(s): NONE
      

      【讨论】:

        【解决方案3】:

        通过以下设置,它可以与liquibase-hibernateliquibase-gradle 扩展一起使用:

        plugins {
            id 'org.liquibase.gradle' version '2.0.1'
        }
        
        dependencies {
            implementation 'org.liquibase:liquibase-core:3.8.0'
        
            liquibaseRuntime 'org.liquibase.ext:liquibase-hibernate5:3.8'
            liquibaseRuntime sourceSets.main.runtimeClasspath
            liquibaseRuntime sourceSets.main.output
        }
        
        def props = new Properties()
        file("src/main/resources/liquibase.properties").withInputStream { props.load(it) }
        
        diff.dependsOn assemble
        diffChangeLog.dependsOn assemble
        
        liquibase {
            activities {
                main {
                    changeLogFile props.getProperty("liquibase.changelog.main")
                    referenceUrl props.getProperty("liquibase.changelog.referenceUrl")
                    url props.getProperty("spring.datasource.url")
                    username props.getProperty("spring.datasource.username")
                    password props.getProperty("spring.datasource.password")
                    referenceDriver "liquibase.ext.hibernate.database.connection.HibernateDriver"
                }
            }
        }
        

        这将在指定的更改日志文件中生成更改日志。您可以首先使用gradle generateChangelog 生成初始更改日志,运行应用程序以将这些更改应用到数据库,然后在实体模型中的每次更改后运行gradle diffChangelog 任务以在chanlog 文件中获取这些更改。然后应在再次运行diffChangeLog 任务之前将这些应用到数据库,以防止更改日志中出现重复操作。

        为此,您需要liquibase.properties 中的以下属性:

        liquibase.changelog.main=src/main/resources/db/changelog/db.changelog-master.xml
        liquibase.changelog.classpath=classpath:db/changelog/db.changelog-master.xml
        liquibase.changelog.referenceUrl=hibernate:spring:<MODEL_PACKAGE>?dialect=org.hibernate.dialect.MySQL5Dialect
        

        重要提示:请务必将 &lt;MODEL_PACKAGE&gt; 替换为您的休眠模型所在的包。

        【讨论】:

          【解决方案4】:
          plugins {
              id 'org.liquibase.gradle' version '2.0.1'
          }
          

          在我将构建的资源和类添加到其运行时依赖项后,Gradle liquibase 插件为我工作,如下所示:

          dependencies {
              liquibaseRuntime 'org.liquibase:liquibase-core:3.5.3'
              liquibaseRuntime 'org.liquibase:liquibase-groovy-dsl:2.0.1'
              liquibaseRuntime 'mysql:mysql-connector-java:5.1.34'
              liquibaseRuntime 'org.liquibase.ext:liquibase-hibernate4:3.6'
              liquibaseRuntime 'javax.persistence:javax.persistence-api:2.2'
              liquibaseRuntime files('build/classes/java/main')
              liquibaseRuntime files('build/resources/main')
          
              // Your other dependencies...
          }
          

          我将其主要活动定义为:

          liquibase {
            activities {
              main {
                changeLogFile 'build/liquibase_change_log.xml'
                url 'jdbc:mysql://localhost/YOURDATABASE'
                username 'YOURUSER'
                password 'YOURPASSWORD'
                driver 'com.mysql.jdbc.Driver'
                referenceUrl 'hibernate:classic:/hibernate.cfg.xml'      
              }
            }
          }
          

          请注意,我只是使用经典的 Hibernate 配置来定义源架构。

          liquibase 的 hibernate4 集成在运行 liquibase 的 JVM 的类路径中查找 /hibernate.cfg.xml。它还需要找到您的架构类。

          我还添加了这个:

          diffChangeLog.dependsOn build
          

          【讨论】:

            【解决方案5】:

            解决方案是编写一个调用liquibase diffChangeLog的gradle任务

            在项目根目录下创建liquibase.gradle文件,添加liquibase-hibernate扩展并编写调用liquibase diffChangeLog命令的gradle任务。

            configurations {
              liquibase
            }
            
            dependencies {
              liquibase group: 'org.liquibase.ext', name: 'liquibase-hibernate4', version: 3.5
            }
            
            //loading properties file.
            Properties liquibaseProps = new Properties()
            liquibaseProps.load(new FileInputStream("src/main/resources/liquibase-task.properties"))
            
            Properties applicationProps = new Properties()
            applicationProps.load(new FileInputStream("src/main/resources/application.properties"))
            
            task liquibaseDiffChangelog(type: JavaExec) {
              group = "liquibase"
            
            
              classpath sourceSets.main.runtimeClasspath
              classpath configurations.liquibase
              main = "liquibase.integration.commandline.Main"
            
              args "--changeLogFile=" + liquibaseProps.getProperty('liquibase.changelog.path')+ buildTimestamp() +"_changelog.xml"
              args "--referenceUrl=hibernate:spring:" + liquibaseProps.getProperty('liquibase.domain.package') + "?dialect=" + applicationProps.getProperty('spring.jpa.properties.hibernate.dialect')
              args "--username=" + applicationProps.getProperty('spring.datasource.username')
              args "--password=" + applicationProps.getProperty('spring.datasource.password')
              args "--url=" + applicationProps.getProperty('spring.datasource.url')
              args "--driver=com.mysql.jdbc.Driver"
              args "diffChangeLog"
            }
            
            def buildTimestamp() {
              def date = new Date()
              def formattedDate = date.format('yyyyMMddHHmmss')
              return formattedDate
            }
            

            注意:我使用属性文件将参数传递给 liquibase 命令,您可以直接添加值,但这不是一个好习惯。

            接下来,您需要从项目的 build.gradle 文件中应用 liquibase.gradle 文件。并添加 liquibase 依赖项

            apply from: 'liquibase.gradle'
            //code omitted
            dependencies {
                compile (group: 'org.liquibase', name: 'liquibase-core', version: "3.4.2")
            }
            

            完成此步骤后,liquibase 将完全设置。

            您现在可以使用gradle liquibaseDiffChangeLog 生成 更新日志。

            【讨论】:

            • Could not find method liquibase() for arguments [{group=org.liquibase.ext, name=liquibase-hibernate4, version=3.5}] on object of type org.gradle.api.internal.artifacts.dsl.dependencies.DefaultDependencyHandler. 之类的错误可以解决,但如何解决??
            • 请看一下上面的评论。我相信您的解决方案会起作用,但我无法确定为什么会出现这个问题(我对 gradle 很陌生)。我正在使用gradle version 4.1 谢谢:)
            • @VikrantKashyap 您是否解决了上述错误,如果是,请您分享解决方案,因为我也遇到了同样的错误。谢谢。
            猜你喜欢
            • 2018-08-19
            • 2023-01-13
            • 1970-01-01
            • 2017-03-21
            • 2020-12-13
            • 2016-04-01
            • 1970-01-01
            • 2018-03-20
            • 1970-01-01
            相关资源
            最近更新 更多