【问题标题】:How to use liquibase to generate a changelog from diffs between a database and persistence entities in spring?spring 如何使用 liquibase 从数据库和持久性实体之间的差异生成变更日志?
【发布时间】:2017-12-05 09:12:22
【问题描述】:

请我需要在 spring(基于 JAVA 的配置)中解决上述问题,而不是在 spring boot 中。 我在网上找到的大多数教程都是基于 spring boot 但我的应用程序没有在 spring boot 上运行, 只是春天mvc。 我的类路径中已经有必要的依赖项,即 liquibase-core-3.5.3 和 liquibase-hibernate5-3.6 jars。

我还创建了 liquibase 属性文件(也在类路径中),如下所示

driver=com.mysql.jdbc.Driver
changeLogFile=classpath:db-changelog.xml
url=jdbc:mysql://localhost:3306/mydatabase
username=myusername
password=mypassword
referenceUrl=hibernate:spring:com.mypackage.entity?dialect=org.hibernate.dialect.MySQL5InnoDBDialect
diffChangeLogFile=com/mypackage/dbchangelog/diff-changelog.xml

现在的问题是我如何执行它来生成一个 diff changelog 文件?

【问题讨论】:

    标签: spring hibernate liquibase liquibase-hibernate


    【解决方案1】:

    你必须使用 maven 或 gradle 的 liquibase 插件来完成,这取决于你用于构建的内容。

    Maven plugin 是关于如何运行 liquibase 命令的非常好的文档。

    如果你使用的是gradle,liquibase插件在调用diffChangeLog时会不流畅。

    基于this answer,创建一个名为liquibase.gradle的文件。我已经按照hibernate5 编辑了一些属性,因为它不再支持ImprovedNamingStrategy

    def diffLog = "$projectDir/src/main/resources/db/changelog/db.changelog.yaml"
    
    configurations {
        liquibase
    }
    
    dependencies {
        liquibase 'org.liquibase.ext:liquibase-hibernate5:3.6'
    }
    
    task liquibaseDiffChangelog(type: JavaExec) {
        group = "liquibase"
    
        classpath sourceSets.main.runtimeClasspath
        classpath configurations.liquibase
        main = "liquibase.integration.commandline.Main"
    
        args "--changeLogFile=" + diffLog
        args "--referenceUrl=hibernate:spring:com.mypackage.entity?hibernate.physical_naming_strategy=org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy&dialect=org.hibernate.dialect.MySQL5Dialect"
        args "--username=<username>"
        args "--password=<password>"
        args "--url=jdbc:mysql://<db_host_and_port>/<db_name>"
        args "--referenceDriver=liquibase.ext.hibernate.database.connection.HibernateDriver"
        args "diffChangeLog"
    }
    

    在您的build.gradle 中添加apply from: 'liquibase.gradle'

    现在,要生成 diffChangeLog,请调用 gradle liquibaseDiffChangelog

    请注意,该示例使用 Spring Boot 的类之​​一作为 Hibernate 物理命名策略。你可以参考this answer创建自己的实现。

    【讨论】:

      【解决方案2】:

      这里是 spring bean 配置:

      @Bean
      public SpringLiquibase liquibase() {
          SpringLiquibase liquibase = new SpringLiquibase();
          liquibase.setChangeLog("classpath:db-changelog.xml");
          liquibase.setDataSource(dataSource());
          return liquibase;
      }
      

      和来自 [liquibase - 网站][1] 的 xml 配置

      <bean id="liquibase" class="liquibase.integration.spring.SpringLiquibase">
            <property name="dataSource" ref="myDataSource" />
            <property name="changeLog" value="classpath:db-changelog.xml" />
      
            <!--
            contexts specifies the runtime contexts to use.
            -->
            <property name="contexts" value="test, production" />  
      

      来源:SpringLiquibase——它是代码执行更新,它是默认行为。

      protected void performUpdate(Liquibase liquibase) throws LiquibaseException{
          if (tag != null) {
              liquibase.update(tag, new Contexts(getContexts()), new LabelExpression(getLabels()));
          } else {
              liquibase.update(new Contexts(getContexts()), new LabelExpression(getLabels()));
          }
      }
      

      类 Liquibase 有方法

      public DiffResult diff(Database referenceDatabase,
                             Database targetDatabase, 
                             CompareControl compareControl)
      

      所以,您可以创建自定义 SpringLiquibase 并使用 diff 而不是更新

      public class MyDiffSpringLiquibase extends SpringLiquibase {
      
          @Override
          protected void performUpdate(Liquibase liquibase) throws LiquibaseException {
          Database referenceDatabase = new MySQLDatabase();
          referenceDatabase.setConnection();
      
          Database targetDatabase = new MySQLDatabase();
          targetDatabase.setConnection();
      
          CatalogAndSchema catalogAndSchemaReference = new CatalogAndSchema();
          CatalogAndSchema catalogAndSchemacomparison = new CatalogAndSchema();
      
          Set<Class<? extends DatabaseObject>> finalCompareTypes = null;
          Class<? extends DatabaseObject>[] snapshotTypes = new Class[]{Table.class ,View.class......};
          if (snapshotTypes != null && snapshotTypes.length > 0) {
              finalCompareTypes = new HashSet<Class<? extends DatabaseObject>>(Arrays.asList(snapshotTypes));
          }
      
          CompareControl compareControl = new CompareControl(new CompareControl.SchemaComparison[]{new CompareControl.SchemaComparison(catalogAndSchemaReference, catalogAndSchemacomparison)}, finalCompareTypes);
          liquibase.diff(referenceDatabase, targetDatabase, compareControl);
          }
      }
      

      并将其注册为 bean

      @Bean
      public SpringLiquibase liquibase() {
          SpringLiquibase liquibase = new MyDiffSpringLiquibase ();
          liquibase.setChangeLog("classpath:db-changelog.xml");
          liquibase.setDataSource(dataSource());
          return liquibase;
      }
      

      【讨论】:

      • 这不是我想要的。我已经知道了。请理解我的问题。我需要的是如何从数据库和持久性实体之间的差异生成变更日志?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-01
      • 2012-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多