في
الجزء السابق ، اكتشفنا الميزات الأساسية لـ
Liquibase وكتبنا مثالًا أساسيًا لتطبيق
تمهيد Spring يستخدم Liquibase لتهيئة قاعدة البيانات. يمكن رؤية رمز التطبيق الأساسي الكامل
هنا على جيثب . في هذه المقالة سوف نتحدث عن
البرنامج المساعد لـ liquibase-maven-plugin والميزات الإضافية التي يوفرها لنا لإصدار بنية قاعدة البيانات. لنبدأ بكيفية إنشاء البرامج النصية تلقائيًا باستخدام
وظيفة المقارنة .
لنفترض أننا كنا بحاجة لإجراء بعض التغييرات في هيكل قاعدة البيانات الخاصة بنا. على سبيل المثال ، نريد أن لا يكون
البريد الإلكتروني خاليًا . بالطبع ، لمثل هذا التغيير البسيط ، يمكنك تصحيح الكود والنصوص يدويًا ، لكن ماذا لو كانت هناك المزيد من التغييرات؟ في هذه الحالة ، سوف تساعدنا القدرة على مقارنة قاعدة البيانات المدمجة في Liquibase. ميزة مثيرة للاهتمام أنه يمكنك مقارنة ليس فقط قواعد البيانات ، ولكن أيضا قاعدة بيانات مع مجموعة من الكيانات JPA في تطبيقنا. هذا بالضبط ما سنفعله الآن!
إنشاء برنامج نصي مع التغييرات باستخدام liquibase-diff
في قسم
الإضافات في ملف
pom.xml ، نضيف هذا التصميم المعقد إلى حد ما. هذا هو
البرنامج المساعد لـ
fluibase-maven-plugin ، والذي يرتبط به التبعية لتحليل
كيانات السبات والعمل مع ملفات YAML. سوف يساعدنا المكون الإضافي تلقائيًا في إنشاء برامج
نصية لـ fluibase من خلال مقارنة الهياكل في قاعدتي بيانات أو حتى من خلال مقارنة بنيات البيانات في قاعدة بيانات ومجموعة من الكيانات hiberante في تطبيقنا (هذا هو بالضبط ما
تمت إضافة
liquibase-hibernate5 ).
<plugin> <groupId>org.liquibase</groupId> <artifactId>liquibase-maven-plugin</artifactId> <version>3.8.1</version> <configuration> <propertyFile>${project.build.outputDirectory}/liquibase-maven-plugin.properties</propertyFile> <systemProperties> <user.name>your_liquibase_username</user.name> </systemProperties> <logging>info</logging> </configuration> <dependencies> <dependency> <groupId>org.liquibase.ext</groupId> <artifactId>liquibase-hibernate5</artifactId> <version>3.6</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-jpa</artifactId> <version>2.2.0.RELEASE</version> </dependency> </dependencies> </plugin>
انتبه إلى إعداد اسم المستخدم. إنه اختياري ، لكن بدونه سيشير Liquibase في البرامج النصية التي تم إنشاؤها إلى اسم مستخدم نظام التشغيل الحالي الذي يتم تشغيل المكون الإضافي بموجبه.
يمكن كتابة إعدادات المكون الإضافي مباشرةً إلى pom.xml أو تمريرها كمعلمات لسطر الأوامر عند استدعاء maven ، لكنني أفضل الخيار مع ملف
liquibase-maven-plugin.properties منفصل. سوف محتوياته تبدو مثل هذا.
changeLogFile= @project.basedir@/src/main/resources/db/changelog/db.changelog-master.yaml url= jdbc:mysql://localhost:3306/geek_db?createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&useSSL=false&useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC username= dbusername password= dbpassword driver= com.mysql.cj.jdbc.Driver referenceUrl= hibernate:spring:ru.usharik.liquibase.demo.persist.model?dialect=org.hibernate.dialect.MySQLDialect diffChangeLogFile= @project.basedir@/src/main/resources/db/changelog/db.changelog-@timestamp@.yaml ignoreClasspathPrefix= true
يجدر الانتباه إلى معلمات
url و
referenceUrl . سيكون البرنامج النصي الذي سينشئ قاعدة بيانات fluibase بعد المقارنة هو الفرق بين القاعدة باستخدام رابط referenceUrl والقاعدة باستخدام
رابط url . إذا قمت بتشغيل هذا البرنامج النصي لاحقًا على القاعدة باستخدام
رابط url ، فسيصبح هو نفسه الموجود في الارتباط referenceUrl. يجب الانتباه بشكل خاص إلى الرابط referenceUrl. كما ترون ، فإنه لا يشير إلى قاعدة البيانات ، ولكن إلى حزمة تطبيقنا التي توجد بها فئات الكيانات. بفضل هذا ، يمكننا الآن العثور على برنامج نصي سيضيف إلى قاعدة البيانات التغييرات التي تم إجراؤها في الكود.
نحتاج الآن إلى تهيئة مكون maven-resource-plugin لاستبدال العناصر النائبة في ملف الإعدادات ، مثل
@project.basedir@
و
@timestamp@
. للقيام بذلك ، أضف قسم
الموارد في النموذج التالي إلى قسم الإنشاء
<resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> <includes> <include>*.properties</include> </includes> </resource> <resource> <directory>src/main/resources</directory> <filtering>false</filtering> <includes> <include>**/*.*</include> </includes> </resource> </resources>
بالمناسبة ، يغير Spring boot التنسيق القياسي
للعناصر النائبة التي يتم ملؤها باستخدام
maven-resource-plugin من
${smth}
إلى
@smth@
. الحقيقة هي أن العناصر النائبة من
@smth@
في Spring Boot تُستخدم لاستبدال متغيرات البيئة ومعلمات تطبيق Spring Boot نفسه.
أيضًا ، قمنا بتغيير قسم
الخصائص قليلاً في
pom.xml لتعيين القيمة لمتغير
الطابع الزمني بالتنسيق الذي نحتاجه. للأسف ، قد يحتوي التنسيق القياسي على أحرف محظورة في أسماء الملفات لبعض أنظمة التشغيل.
<properties> <java.version>1.8</java.version> <timestamp>${maven.build.timestamp}</timestamp> <maven.build.timestamp.format>yyyyMMdd-HHmmssSSS</maven.build.timestamp.format> </properties>
الآن دعونا نغير حقل البريد الإلكتروني في فئة المستخدم
@Column(name = "email", nullable = false) private String email;
أخيرًا ، قم بتشغيل الأمر build باستخدام
liquibase-maven-plugin للمقارنة.
mvn clean install liquibase:diff -DskipTests=true
في هذه الحالة ، نحتاج إلى إعادة إنشاء المشروع بالكامل ، لأن المكون الإضافي (liquibase: diff) سيستخدم مصادر غير مترجمة ، ولكن سيتم تجميع ملفات فئة الكيانات من المجلد
الهدف للتحليل.
إذا تم تنفيذ كل شيء بشكل صحيح ، فبعد التنفيذ الناجح للأمر في مجلد
الموارد / db / changelog ، سترى ملفًا يحمل الاسم
db.changelog-20190723-100748666.yaml . نظرًا لحقيقة أننا نستخدم التاريخ والوقت الحاليين في اسم الملف ، فمع كل عملية إطلاق ، سيكون لدينا ملف جديد مناسب تمامًا. إذا كنت قد أنشأت بالفعل قاعدة بيانات بهيكل الجدول المقابل للدرس السابق ، فعندئذ يجب أن تكون محتويات الملف هكذا.
databaseChangeLog: - changeSet: id: 1563876485764-1 author: your_liquibase_username (generated) changes: - addNotNullConstraint: columnDataType: varchar(255) columnName: email tableName: users
كما ترون ، فإن هذا البرنامج النصي يجعل التغيير الذي تم في الكود بالضبط. كتمرين ، أوصي بتشغيل هذا البرنامج النصي مقابل قاعدة بيانات فارغة وإلقاء نظرة على النتيجة.
بعد ذلك ، يمكننا ببساطة نسخ مجموعة التغيير من هذا الملف إلى
db.changelog-master.yaml أو يمكننا توصيل هذا الملف به بتعليمات
- include: file: db.changelog-20190723-100748666.yaml relativeToChangelogFile: true
تحتاج أيضًا في هذا الملف إلى تحديد
logicalFilePath: db/changelog/db.changelog-20190723-100748666.yaml
، على غرار الطريقة التي تم بها ذلك في
db.changelog-master.yaml .
سيساعد ذلك في التغلب على بعض المشكلات المحتملة عند استخدام
المكوّن الإضافي المدمج من المواليس
المساعد والموليب السائل في المليون في التطبيق. بعد ذلك ، أعد تشغيل التطبيق أو قم بتشغيل الأمر:
mvn liquibase:update
دعنا نحاول إجراء تغيير أكثر تعقيدًا في الكود. على سبيل المثال ، قم بإضافة جدول دور سيكون له علاقة من أطراف إلى جدول بجدول المستخدم.
@Entity @Table(name = "roles") public class Role implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Long id; @Column(name = "name", unique = true, nullable = false) private String name; @ManyToMany(mappedBy = "roles") private Set<User> users;
وفي جدول المستخدمين نضيف
@ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "users_roles", joinColumns = @JoinColumn(name = "user_id"), inverseJoinColumns = @JoinColumn(name = "role_id")) private Set<Role> roles;
بعد بدء المقارنة ، نحصل على ملف بالمحتويات التالية
databaseChangeLog: - changeSet: id: 1563877765929-1 author: your_liquibase_username (generated) changes: - createTable: columns: - column: autoIncrement: true constraints: primaryKey: true primaryKeyName: rolesPK name: id type: BIGINT - column: constraints: nullable: false name: name type: VARCHAR(255) tableName: roles - changeSet: id: 1563877765929-2 author: your_liquibase_username (generated) changes: - createTable: columns: - column: constraints: nullable: false name: user_id type: BIGINT - column: constraints: nullable: false name: role_id type: BIGINT tableName: users_roles - changeSet: id: 1563877765929-3 author: your_liquibase_username (generated) changes: - addPrimaryKey: columnNames: user_id, role_id tableName: users_roles - changeSet: id: 1563877765929-4 author: your_liquibase_username (generated) changes: - addUniqueConstraint: columnNames: name constraintName: UC_ROLESNAME_COL tableName: roles - changeSet: id: 1563877765929-5 author: your_liquibase_username (generated) changes: - addForeignKeyConstraint: baseColumnNames: user_id baseTableName: users_roles constraintName: FK2o0jvgh89lemvvo17cbqvdxaa deferrable: false initiallyDeferred: false referencedColumnNames: id referencedTableName: users - changeSet: id: 1563877765929-6 author: your_liquibase_username (generated) changes: - addForeignKeyConstraint: baseColumnNames: role_id baseTableName: users_roles constraintName: FKj6m8fwv7oqv74fcehir1a9ffy deferrable: false initiallyDeferred: false referencedColumnNames: id referencedTableName: roles
يمكننا أيضًا إضافة هذا الملف بسهولة إلى البرامج النصية العاملة.
دحر التغييرات
الآن لنرى كيف نعيد التغييرات التي تم إجراؤها. لسبب ما ، لا يمكن استخدام تلك المعرّفات التي حددناها في changeSets للتراجع عنها. هناك ثلاثة خيارات ، حدد نقطة التراجع
- من خلال عدد من مجموعات التغيير العد من الحالي
- بعد تاريخ التغيير
- عبر علامة (تعيين باستخدام changeSet من نوع خاص)
تم تعيين العلامة على النحو التالي.
- changeSet: id: some_uniqui_id author: liquibase_user_name changes: - tagDatabase: tag: db_tag
حسنًا ، الأوامر الخاصة بالطرق الثلاث المدرجة للتراجع
mvn liquibase:rollback -Dliquibase.rollbackTag=db_tag mvn liquibase:rollback -Dliquibase.rollbackCount=1 mvn liquibase:rollback "-Dliquibase.rollbackDate=Jun 03, 2017"
وأخيرا ، بعض المواد الإضافية
- رمز لهذه المادة
- حول التراجع في Liquibase
- حول الهجرة مع Liquibase
- Liquibase على جيثب
- مقال جيد جدًا حول الطرق المختلفة لإصدار قاعدة بيانات
بالطبع ، سأكون سعيدًا جدًا بأي تعليقات أو إضافات أو إيضاحات ، إلخ.