Как использовать liquibase для генерации журнала изменений из различий между базой данных и персистентными сущностями весной?

Пожалуйста, мне нужно решение вышеуказанного вопроса весной (на основе конфигурации JAVA), а НЕ в весенней загрузке. Большинство учебных пособий, которые я нашел в Интернете, основаны на весенней загрузке, но мое приложение не работает на весенней загрузке, просто весенний mvc. У меня есть необходимые зависимости, уже находящиеся в моем classpath, это банки liquibase-core-3.5.3 и liquibase-hibernate5-3.6.

Я также создал файл свойств liquibase (тоже в classpath), как показано ниже

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?

2 ответа

Вы должны будете сделать это, используя плагин liquibase для maven или gradle, в зависимости от того, что вы используете для сборки.

Плагин Maven также очень хорошая документация о том, как вы можете запускать команды liquibase.

Если вы используете Gradle, плагин liquibase не работает гладко при вызове diffChangeLog,

На основе этого ответа создайте файл с именем 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"
}

добавлять apply from: 'liquibase.gradle' в вашем build.gradle,

Теперь, чтобы сгенерировать diffChangeLog, вызовите gradle liquibaseDiffChangelog,

Обратите внимание, что в примере используется один из классов весенней загрузки в качестве стратегии именования Hibernate. Вы можете создать свою собственную реализацию, обратившись к этому ответу.

Вот конфигурация бобов весны:

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

и xml config от [liquibase - веб-сайт][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" />  

из источника: 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
public SpringLiquibase liquibase() {
    SpringLiquibase liquibase = new MyDiffSpringLiquibase ();
    liquibase.setChangeLog("classpath:db-changelog.xml");
    liquibase.setDataSource(dataSource());
    return liquibase;
}
Другие вопросы по тегам