3

Please i need solution to the above question in spring (JAVA based config) and NOT in spring boot. Most of the tutorials i found online are based on spring boot but my app is not running on spring boot, just spring mvc. I have the necessary dependencies already in my classpath, that's liquibase-core-3.5.3 and liquibase-hibernate5-3.6 jars.

I have also created liquibase properties file (in classpath too) as shown below

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

The problem now is how do i execute it to generate a diff changelog file?

Perry
  • 312
  • 1
  • 4
  • 12

2 Answers2

2

You will have to do it using liquibase plugin for maven or gradle depending on what you use for build.

Maven plugin as very good documentation as to how you can run liquibase commands.

If you are using gradle, liquibase plugin doesn't work smoothly when calling diffChangeLog.

Based on this answer, create a file named liquibase.gradle. I have edited some properties as per hibernate5 since it doesn't support ImprovedNamingStrategy anymore.

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

Add apply from: 'liquibase.gradle' in your build.gradle.

Now, to generate diffChangeLog, invoke gradle liquibaseDiffChangelog.

Please note the example uses one of spring boot's class as Hibernate Physical Naming Strategy. You can create your own implementation by referring to this answer.

Yogesh Badke
  • 4,249
  • 2
  • 15
  • 23
0

here is spring bean config :

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

and xml config from [liquibase - web site][1]

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

from source : SpringLiquibase -- it's code execute update , it's default behaviour .

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()));
    }
}

class Liquibase has method

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

so , you can create custom SpringLiquibase and use diff instead of update

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);
    }
}

and register it as bean

@Bean
public SpringLiquibase liquibase() {
    SpringLiquibase liquibase = new MyDiffSpringLiquibase ();
    liquibase.setChangeLog("classpath:db-changelog.xml");
    liquibase.setDataSource(dataSource());
    return liquibase;
}
xyz
  • 5,228
  • 2
  • 26
  • 35
  • 1
    This is not what I want. I know this already. Please understand my question. What i need is how to generate a changelog from differences between a database and persistence entities? – Perry Jul 01 '17 at 17:47