Как отключить опускание таблицы и столбца при использовании mvn liquibase: diff? - PullRequest
2 голосов
/ 30 октября 2019

Я настраиваю процесс выпуска, чтобы максимально легко обновить нашу производственную среду.

Чтобы добиться этого в отношении базы данных, я выбрал liquibase. Каждый раз при обновлении среды:

  1. Код доставляется на серверы,
  2. mvn liquibase:diff запускается для создания журнала изменений с предыдущей версией
  3. mvn spring-boot:runзапускается, чтобы запустить приложение и выполнить liquibase с новым changeLog, и, таким образом, адаптировать базу данных из только что доставленного объекта кода.

Проблема заключается в том, что если поле вjava @Entity, например, перемещен в другую сущность, liquibase удалит столбец без переноса данных в новое местоположение поля.

Так что мой вопросесть, можем ли мы сконфигурировать жидкость для избежать столбца и таблицы drop ? Чтобы иметь возможность копировать данные в их новые местоположения и после этого эффективно удалять столбец (или таблицу) навсегда?

Мы используем spring-boot 2.1.2 иПлагин liquibase maven 3.4.1 . Наша база данных находится на MySQL 5.7.27 .

Я пытаюсь найти способ экспорта всей базы данных создание / изменение changeSet в одну changeLog.xml ивсе капля changeSet в другой changeLog.xml. Таким образом, мы можем выполнить между этими двумя changeLog, третий changeLog, предназначенный для копирования данных в новое место. Бу не нашел решения в документации по жидкостям: https://www.liquibase.org/documentation/diff.html

Для иллюстрации моего примера:

v1 :

@Entity
public class Person {
     private long id;
     private String name;
     private String phoneNumber;
}

Стал

v2 : (создание сущности Телефон для замены поля номер телефона сущности Персона )

@Entity
public class Person {
     private long id;
     private String name;
     private Phone phone;
}

@Entity
public class Phone {
    private long id;
    private String phoneNumber;
    private String brand;
}

Таким образом, когда v2 доставляется на сервер и запускается mvn liquibase:diff, результат changeLog будет drop column phoneNumber и создавать столбец телефон в таблице человек . Без переноса данных из таблицы person , поданной phoneNumber в новую таблицу phone в поле phoneNumber .

хочувыполнить changeLog (вручную), чтобы скопировать Person.phoneNumber в новую сущность Phone.phoneNumber .

Возможно ли это? Или есть какой-то трюк, чтобы сделать это правильно? Или, может быть, я плохо использую жидкость для достижения этой цели?

Большое спасибо!

1 Ответ

1 голос
/ 30 октября 2019

Может быть, я что-то упускаю, но, насколько я понимаю, diff - не всесильный инструмент, который освободит вас от любой ответственности.

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

Поскольку diff действительно очень мощная команда, у нее есть свои недостатки.

Ознакомьтесь с этой статьей: Проблема с различиями в базе данных

Теоретически, инструмент сравнения может также проверять наличие новых, обновленных и отсутствующих данных между базами данных, но на практике этоне может работать по двум причинам:

  • Производительность. По мере роста вашего набора данных объем информации для сравнения увеличивается до тех пор, пока он не станет неуправляемым.
  • Изменение данных. Во время разработки тестовые данные часто добавляются в базу данных разработки, которую не следует копировать в другие базы данных. Кроме того, в тестовые и производственные базы данных могут быть добавлены новые данные, которые не следует удалять только потому, что их нет в базе данных разработки.

В вашем случае я бы что-то сделалкак это:

  1. Создать новую таблицу phone
  2. Добавить столбец person.phone_id
  3. Копировать данные из person.phone_number в phone.phone_number
  4. Копирование данных из phone.id в person.phone_id
  5. Создание ограничения внешнего ключа между person и phone
  6. Удаление person.phone_number

код может быть таким:

<createTable tableName="phone">
    <column name="id" autoIncrement="true" type="bigserial">
        <constraints primaryKey="true" primaryKeyName="pk_phone"/>
    </column>
    <column name="phone_number" type="varchar(30)"/>
    <column name="brand" type="varchar(255)"/>
</createTable>
<addColumn tableName="person">
    <column name="phone_id" type="bigserial"/>
</addColumn>
<update tableName="phone">
    <column name="phone_number" valueComputed="(select p.phone_nubmer from person p)"/>
</update>
<comment>Assuming that person.phone_number is unique</comment>
<update tableName="person">
    <column name="phone_id" valueComputed="(select p.id from person p where p.phone_number = phone_number)"/>
</update>
<addForeignKeyConstraint baseTableName="person" baseColumnNames="phone_id"
    constraintName="person_phone_id_phone_id_fk"
    referencedTableName="phone" referencedColumnNames="id"/>
<dropColumn tableName="person" columnName="phone_number"/>
...