Liquibase و Maven

مقدمة


Liquibase هو نظام للتحكم في إصدار قاعدة البيانات ، وهذا يتعلق بشكل أساسي بالهيكل ، وإلى حد أقل ، محتويات قاعدة البيانات. في الوقت نفسه ، وصف قاعدة البيانات من ناحية مجردة تمامًا ويسمح باستخدام قواعد بيانات إدارة قواعد البيانات المختلفة في المستوى الأدنى ، ومن ناحية أخرى ، يمكنك دائمًا التبديل إلى لهجة SQL الخاصة بنظام قاعدة بيانات إدارة قواعد البيانات (DBMS) ، والذي يتميز بالمرونة التامة. Liquibase هو مشروع مفتوح المصدر تم إنشاؤه ويستخدم بنشاط خارج بيئة Java الأصلية ولا يتطلب معرفة متعمقة من Java للعمل. تاريخياً ، استخدم تنسيق XML لوصف البنية الأساسية والتغييرات الأساسية ، ولكن الآن يتم دعم YAML و JSON بشكل متوازٍ.


في هذه المقالة ، سنوجز باختصار تجربة الأجيال السابقة وسنركز على العمل مع Liquibase باستخدام Maven. سوف نستخدم Ubuntu كنظام تشغيل اختبار.


مقالات أخرى حول Liquibase



بيئة الإعداد


هناك عدة طرق لبدء تشغيل Liquibase ، إلا أنه من الأنسب استخدام Maven أو Gradle.


sudo apt install maven mvn -version 

هنا pom.xml بمثابة Makefile - أنه يحتوي بالفعل على جميع التبعيات والإعدادات والتوصيفات اللازمة.


pom.xml
 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.test.db</groupId> <artifactId>db</artifactId> <version>1.0.0</version> <name>db</name> <description>Test Database</description> <packaging>pom</packaging> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <slf4j.version>1.7.24</slf4j.version> <logback.version>1.2.3</logback.version> <liquibase.version>3.6.2</liquibase.version> <postgresql.version>42.2.5</postgresql.version> <snakeyaml.version>1.23</snakeyaml.version> </properties> <dependencies> <!--Logging--> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>log4j-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>jcl-over-slf4j</artifactId> <version>${slf4j.version}</version> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>${logback.version}</version> </dependency> <!--JDBC drivers--> <dependency> <groupId>org.postgresql</groupId> <artifactId>postgresql</artifactId> <version>${postgresql.version}</version> </dependency> <dependency> <groupId>org.liquibase</groupId> <artifactId>liquibase-core</artifactId> <version>${liquibase.version}</version> </dependency> <dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>${snakeyaml.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>${liquibase.version}</version> <configuration> <propertyFile>${profile.propertyFile}</propertyFile> <changeLogFile>${profile.changeLogFile}</changeLogFile> <dataDir>${profile.dataDir}</dataDir> <!-- log --> <verbose>${profile.verbose}</verbose> <logging>${profile.logging}</logging> <promptOnNonLocalDatabase>false</promptOnNonLocalDatabase> </configuration> </plugin> </plugins> </build> <profiles> <!-- Development settings, -Denv=dev --> <profile> <id>dev</id> <activation> <property> <name>env</name> <value>dev</value> </property> </activation> <properties> <profile.propertyFile>dev/liquibase.properties</profile.propertyFile> <profile.changeLogFile>dev/master.xml</profile.changeLogFile> <profile.dataDir>dev/data</profile.dataDir> <profile.verbose>true</profile.verbose> <profile.logging>debug</profile.logging> </properties> </profile> <!-- Production settings, -Denv=prod --> <profile> <id>prod</id> <activation> <property> <name>env</name> <value>prod</value> </property> </activation> <properties> <profile.propertyFile>prod/liquibase.properties</profile.propertyFile> <profile.changeLogFile>prod/master.xml</profile.changeLogFile> <profile.dataDir>prod/data</profile.dataDir> <profile.verbose>false</profile.verbose> <profile.logging>info</profile.logging> </properties> </profile> </profiles> </project> 

نطلق التحديث


بعد الانتهاء من pom.xml ، يمكننا البدء في تحديث قاعدة البيانات - الأمر liquibase: update.


لهذا نحتاج:


  • ملف liquibase.properties مع إعدادات للاتصال بقاعدة البيانات (اسم المستخدم / كلمة المرور وربما غيرها من المعالم)
  • ملف XML مع التغييرات الأساسية
  • ش تحديث قاعدة البيانات النصي لبدء التشغيل

ملف إعدادات اتصال قاعدة البيانات


liquibase.properties


 username=test password=test referenceUsername=test #     #url=jdbc:postgresql://dev/test #referenceUrl=jdbc:postgresql://dev/test_reference 

تغييرات قاعدة الملف


المفهوم الرئيسي لل fluibase هو ما يسمى التغييرات الأساسية (Chanets). يمكن أن تشمل كل من التغييرات الهيكلية وتغيير البيانات. يستخدم Liquibase جداول databasechangelog و databasechangeloglock لمراقبة التغييرات المطبقة.


 <?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:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog-ext http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-ext.xsd http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.6.xsd"> <changeSet context="legacy" author="author (generated)" id="1"> <createTable tableName="test"> <column autoIncrement="true" name="id" type="SERIAL"> <constraints nullable="false"/> </column> <column name="user_name" type="VARCHAR(255)"/> <column name="preferences" type="TEXT"/> </createTable> </changeSet> </databaseChangeLog> 

تحديث قاعدة البيانات النصي لبدء التشغيل


هنا liquibase: يتم تنفيذ التحديث لملف تعريف dev والقاعدة من liquibase.url ، المحدد في تنسيق JDBC القياسي. بعد التحديث ، يظهر الجدول المشار إليه في changeSet وجدولين للخدمة databasechangelog و databasechangeloglock في قاعدة البيانات .


 #!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified" 

إنشاء SQL دون تحديث قاعدة البيانات


في بعض الأحيان ، قبل بدء التغييرات ، تحتاج إلى إلقاء نظرة على محتويات الطلبات التي تم إنشاؤها. و liquibase: updateSQL و liquibase: أوامر rollbackSQL هي لهذا الغرض المقصود.


 #!/usr/bin/env bash mvn liquibase:updateSQL\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified" > /tmp/script.sql 

المزيد عن changeSet


يمكن أن تكون التغييرات بتنسيقات مختلفة ، بما في ذلك sql العادية أو في ملف منفصل.


قد يتضمن كل تغيير مقطعًا للتراجع يسمح لك باستعادة التغييرات باستخدام الأمر liquibase: rollback . بالإضافة إلى ذلك ، يمكنك استخدام tagDatabase لتمييز التغييرات ، على سبيل المثال ، للتراجع هناك بسهولة أكبر.


تنسيق عادي


 <changeSet context="legacy" author="author (generated)" id="1"> <createTable tableName="test"> <column autoIncrement="true" name="id" type="SERIAL"> <constraints primaryKey="true" primaryKeyName="test_pkey"/> </column> <column name="c1" type="VARCHAR(255)"/> <column name="c2" type="INTEGER"/> <column name="c3" type="SMALLINT"/> <column name="c4" type="VARCHAR(255)"/> <column name="c5" type="TEXT"/> <column name="c6" type="VARCHAR(255)"/> </createTable> </changeSet> 

مزود المضمنة


 <changeSet context="legacy" author="author" id="1-domain-some-domain"> <sql> CREATE DOMAIN public.some_domain AS bigint; ALTER DOMAIN public.some_domain OWNER TO test; </sql> <rollback> DROP DOMAIN public.some_domain; </rollback> </changeSet> 

ملف SQL


 <changeSet context="legacy" author="author" id="1-user"> <sqlFile dbms="postgresql" path="sql/some.sql" relativeToChangelogFile="true" /> <rollback> delete from "some"; </rollback> </changeSet> 

العلامات


 <changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet> 

إطلاق السياقات


لإدارة أكثر ملاءمة للتكوينات المختلفة ، على سبيل المثال ، التطوير / الإنتاج ، يمكن استخدام السياقات. يتم تحديد السياق في سمة changeSet للسياق ثم يتم تشغيله بواسطة Maven باستخدام معلمة -Dcontexts.


التغيير مع السياق


 <changeSet context="legacy" author="author" id="1-initial-changeset"> <tagDatabase tag="initial"/> </changeSet> 

تحريك تغييرات السياق


 #!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy 

دحر التغييرات


العملية هي عكس التحديث ، وفي معظم الحالات يتم دعمها تلقائيًا. بالنسبة للآخرين ، تكون المهمة ممكنة من خلال قسم الاستعادة. يتم تشغيله بواسطة الأمر liquibase: rollback.


التغيير مع التراجع


 <changeSet context="legacy" author="author" id="1-domain-some-domain"> <sql> CREATE DOMAIN public.some_domain AS bigint; ALTER DOMAIN public.some_domain OWNER TO test; </sql> <rollback> DROP DOMAIN public.some_domain; </rollback> </changeSet> 

إطلاق التراجع


 #!/usr/bin/env bash mvn liquibase:update\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test?prepareThreshold=0&stringtype=unspecified"\ -Dliquibase.contexts=non-legacy 

مقارنة


في التطوير ، من الملائم استخدامه لمقارنة قاعدتي بيانات موجودتين للتغييرات التي تم إجراؤها. في الإعدادات (أو معلمات التشغيل) ، ستحتاج إلى إضافة رابط إلى قاعدة البيانات المرجعية والبيانات للوصول إليها.


liquibase.properties


 referenceUsername=test referenceUrl=jdbc:postgresql://dev/test_reference 

مقارنة الدائرة


مقارنة مخططات url و referenceUrl.


 #!/usr/bin/env bash mvn liquibase:diff\ -Denv=dev\ -Dliquibase.referenceUrl="jdbc:postgresql://dev/test?prepareThreshold=0"\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.diffChangeLogFile=dev/diff.xml 

إنقاذ المخطط


قد يكون من المفيد أيضًا حفظ مخطط قاعدة البيانات الحالي ، مع أو بدون بيانات. يجب ألا يغيب عن البال أن Liquibase يحفظ مخططًا لا يتطابق تمامًا مع الأصل ، على سبيل المثال ، يجب إضافة النطاقات المستخدمة أو الميراث بشكل منفصل (انظر القيود).


حفظ مخطط دون أخذ البيانات في الاعتبار


حفظ مخطط قاعدة بيانات موجودة.


 #!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml 

حفظ مخطط مع البيانات


حفظ مخطط قاعدة بيانات موجودة مع البيانات.


 #!/usr/bin/env bash mvn liquibase:generateChangeLog\ -Denv=dev\ -Dliquibase.url="jdbc:postgresql://dev/test_reference?prepareThreshold=0"\ -Dliquibase.outputChangeLogFile=dev/changelog.xml 

القيود والمشاكل


العمل مع البيانات الثنائية في قاعدة البيانات


هناك بعض المشكلات المتعلقة بتحميل البيانات الثنائية ومقارنتها واستخدامها ، لا سيما مشكلة إنشاء التغييرات.



الوراثة والأعمدة المشتركة



شفرة المصدر



حلول بديلة


Flyway


جنبا إلى جنب مع Liquibase تحظى بشعبية في مجتمع جافا - http://flywaydb.org/documentation


سقيتش


بيرل مكافئ - http://sqitch.org


Fluentmigrator


النظير لـ .Net - https://github.com/schambers/fluentmigrator


دبجيني


التناظرية لروبي - http://dbgeni.appsintheopen.com/manual.html


التطبيقات


هيكل المشروع


 pom.xml - maven makefile dev liquibase.properties - login/password etc master.xml - changesets 

كيفية إضافة السائل إلى مشروع قائم



كيف تعمل التغييرات القاعدة



المزيد عن تغيير الشكل



المزيد عن التحديث



المزيد عن تغيير الجيل



المزيد عن SQL مخصص



معالجة أنواع البيانات الخاصة بقاعدة البيانات


 <createTable tableName="t_name"> ... <column name="doubleArray" type="DOUBLE_ARRAY"/> ... </createTable> <modifySql dbms="postgresql"> <replace replace="DOUBLE_ARRAY" with="double precision[][]"/> </modifySql> 

أخرى


Source: https://habr.com/ru/post/ar436994/


All Articles