Механізм перетворення моделі структури БД у вигляді Liquibase ChangeSet
| 🌐 Цей документ доступний українською та англійською мовами. Використовуйте перемикач у правому верхньому куті, щоб змінити версію. |
1. Функціональні сценарії
-
Створення Diff Document на основі DataModelSnapshot бази даних (поточна версія та версія змін) у форматі .json відповідно до вимог.
-
Створення Xml liquibase Changesets на основі згенерованого Diff Document.
2. Out of scope
-
Операція видалення для AccessRule
3. Технологічний стек
| Технологія / Бібліотека | Версія | Ліцензія | Документація | Опис |
|---|---|---|---|---|
Guava |
31.1-jre |
Apache License 2.0 |
Guava — Google бібліотека для роботи з колекціями в Java. |
4. Компонент Diff calculator
Компонент Diff calculator на основі DataModelSnapshot створює Diff Document. Так як DataModelSnapshot має структуру на основі Map, то для підрахунку різниці використовується бібліотека Guava.
| Підрахунок різниці між двома станами структури БД на тестових даних займає 30 мс. |
4.1. Приклад згенерованого Diff Document
{
"tablesToAdd":{
"application_type":{
"name":"application_type",
"remarks":"Довідник типів заяв",
"columns":{
"name":{
"name":"name",
"remarks":"Тип заяви",
"type":"text",
"notNullFlag":true,
"tableName":"application_type"
},
"application_type_id":{
"name":"application_type_id",
"remarks":"Ідентифікатор типів заяв",
"type":"uuid",
"defaultValue":"uuid_generate_v4()",
"notNullFlag":true,
"tableName":"application_type"
},
"constant_code":{
"name":"constant_code",
"remarks":"Символьна константа",
"type":"text",
"notNullFlag":true,
"tableName":"application_type"
}
},
"primaryKey":{
"name":"pk_application_type_id",
"columns":[
{
"name":"application_type_id",
"sorting":"ASC"
}
],
"tableName":"application_type"
},
"uniqueConstraints":{
"application_type_name_key":{
"name":"application_type_name_key",
"columns":[
{
"name":"name",
"sorting":"ASC"
}
],
"tableName":"application_type"
}
}
}
},
"tablesToEdit":{
"staff":{
"attributesToEdit":{
"remarks":"Кадровий склад"
},
"columnsToAdd":{
"researches":{
"name":"researches",
"remarks":"Масив ідентифікаторів досліджень",
"type":"_uuid",
"notNullFlag":false,
"tableName":"staff"
}
},
"columnsToEdit":{
"education":{
"remarks":"Освіта, фах",
"defaultValue":"Юридичний факультет"
}
},
"foreignKeysToAdd":{
"fk_staff_status":{
"name":"fk_staff_status",
"targetTable":"staff_status",
"columnPairs":[
{
"sourceColumnName":"staff_status_id",
"targetColumnName":"staff_status_id"
}
],
"sourceTable":"staff"
},
"fk_staff_laboratory_new":{
"name":"fk_staff_laboratory_new",
"targetTable":"laboratory",
"columnPairs":[
{
"sourceColumnName":"laboratory_id",
"targetColumnName":"laboratory_id"
}
],
"sourceTable":"staff"
}
},
"foreignKeysToDelete":{
"fk_staff_laboratory":{
"name":"fk_staff_laboratory",
"targetTable":"laboratory",
"columnPairs":[
{
"sourceColumnName":"laboratory_id",
"targetColumnName":"laboratory_id"
}
],
"sourceTable":"staff"
}
},
"indicesToAdd":{
"ix_staff_staff_status__staff_status_id":{
"name":"ix_staff_staff_status__staff_status_id",
"columns":[
{
"name":"staff_status_id",
"sorting":"ASC"
}
],
"tableName":"staff"
},
"ix_staff_laboratory__laboratory_id_new":{
"name":"ix_staff_laboratory__laboratory_id_new",
"columns":[
{
"name":"laboratory_id",
"sorting":"ASC"
}
],
"tableName":"staff"
}
},
"indicesToDelete":{
"ix_staff_laboratory__laboratory_id":{
"name":"ix_staff_laboratory__laboratory_id",
"columns":[
{
"name":"laboratory_id",
"sorting":"ASC"
}
],
"tableName":"staff"
}
}
}
},
"accessRulesToAdd":{
"1":{
"permissionId":"1",
"roleName":"isAuthenticated",
"objectName":"laboratory",
"columnName":"edrpou",
"operation":"SELECT"
}
}
}
5. Компонент LiquibaseDataModelSerializer
Компонент LiquibaseDataModelSerializer на основі Diff Document генерує Liquibase XML-Changelog за наступним алгоритмом:
-
Отримуємо Liquibase ChangeLog
-
На основі Diff Document формуємо Liquibase Changes
-
Додаємо Liquibase Changes до потрібного Liquibase ChangeSet або створюємо новий
-
Liquibase на основі оновленого Liquibase ChangeLog генерує Liquibase XML-Changelog
5.1. Приклад згенерованого Liquibase XML-Changelog
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:ext="http://www.liquibase.org/xml/ns/dbchangelog-ext"
xmlns:pro="http://www.liquibase.org/xml/ns/pro"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext
https://nexus-public-mdtu-ddm-edp-cicd.apps.cicd2.mdtu-ddm.projects.epam.com/repository/extensions/com/epam/digital/data/platform/liquibase-ext-schema/latest/liquibase-ext-schema-latest.xsd
http://www.liquibase.org/xml/ns/pro http://www.liquibase.org/xml/ns/pro/liquibase-pro-4.6.xsd
http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.6.xsd">
<changeSet author="system" id="id" objectQuotingStrategy="LEGACY">
<createTable ext:isObject="false" remarks="Довідник типів заяв" tableName="application_type">
<column name="name" remarks="Тип заяви" type="text">
<constraints nullable="false"/>
</column>
<column defaultValue="uuid_generate_v4()" name="application_type_id" remarks="Ідентифікатор типів заяв" type="uuid">
<constraints nullable="false" primaryKey="true" primaryKeyName="pk_application_type_id"/>
</column>
<column name="constant_code" remarks="Символьна константа" type="text">
<constraints nullable="false"/>
</column>
</createTable>
<addUniqueConstraint columnNames="name" constraintName="application_type_name_key" tableName="application_type"/>
<setTableRemarks remarks="Кадровий склад" tableName="staff"/>
<addColumn tableName="staff">
<column name="researches" remarks="Масив ідентифікаторів досліджень" type="_uuid"/>
</addColumn>
<setColumnRemarks columnName="education" remarks="Освіта, фах" tableName="staff"/>
<dropDefaultValue columnName="education" tableName="staff"/>
<addDefaultValue columnName="education" defaultValue="Юридичний факультет" tableName="staff"/>
<dropForeignKeyConstraint baseTableName="staff" constraintName="fk_staff_laboratory"/>
<addForeignKeyConstraint baseColumnNames="staff_status_id" baseTableName="staff" constraintName="fk_staff_status" referencedColumnNames="staff_status_id" referencedTableName="staff_status"/>
<addForeignKeyConstraint baseColumnNames="laboratory_id" baseTableName="staff" constraintName="fk_staff_laboratory_new" referencedColumnNames="laboratory_id" referencedTableName="laboratory"/>
<dropIndex indexName="ix_staff_laboratory__laboratory_id" tableName="staff"/>
<createIndex indexName="ix_staff_staff_status__staff_status_id" tableName="staff">
<column descending="false" name="staff_status_id"/>
</createIndex>
<createIndex indexName="ix_staff_laboratory__laboratory_id_new" tableName="staff">
<column descending="false" name="laboratory_id"/>
</createIndex>
<ext:rbac>
<ext:role name="isAuthenticated">
<ext:table name="laboratory">
<ext:column name="edrpou" read="true"/>
</ext:table>
</ext:role>
</ext:rbac>
</changeSet>
</databaseChangeLog>