1. نظرة عامة
Google Cloud Datastore هي قاعدة بيانات لمستندات NoSQL تم تصميمها للتوسّع التلقائي والأداء العالي وسهولة تطوير التطبيقات.
المعلومات التي ستطّلع عليها
- كيفية استخدام خدمة "تخزين البيانات في السحابة الإلكترونية" لحفظ كائنات جافا واستردادها في Spring Boot
المتطلبات
كيف ستستخدم هذا البرنامج التعليمي؟
ما هو تقييمك لتجربتك في استخدام خدمات Google Cloud Platform؟
2. الإعداد والمتطلبات
إعداد بيئة ذاتية
- سجِّل الدخول إلى Google Cloud Console وأنشئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. إذا لم يكن لديك حساب على Gmail أو Google Workspace، عليك إنشاء حساب.
- اسم المشروع هو الاسم المعروض للمشاركين في هذا المشروع. وهي سلسلة أحرف لا تستخدمها Google APIs. ويمكنك تعديلها في أي وقت.
- يكون رقم تعريف المشروع فريدًا في جميع مشاريع Google Cloud وغير قابل للتغيير (لا يمكن تغييره بعد تحديده). تنشئ Cloud Console سلسلة فريدة تلقائيًا. فعادةً لا تهتم بما هو. في معظم الدروس التطبيقية حول الترميز، يجب الإشارة إلى رقم تعريف المشروع (الذي يتم تحديده عادةً على أنّه
PROJECT_ID
). وإذا لم يعجبك رقم التعريف الذي تم إنشاؤه، يمكنك إنشاء رقم تعريف عشوائي آخر. ويمكنك بدلاً من ذلك تجربة طلبك الخاص ومعرفة ما إذا كان متاحًا. ولا يمكن تغييره بعد هذه الخطوة ويبقى طوال مدة المشروع. - لمعلوماتك، هناك قيمة ثالثة، وهي رقم المشروع، الذي تستخدمه بعض واجهات برمجة التطبيقات. اطّلِع على مزيد من المعلومات حول هذه القيم الثلاث في المستندات.
- بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام الموارد/واجهات برمجة التطبيقات في Cloud. لن يؤدي إكمال هذا الدرس التطبيقي حول الترميز إلى فرض أي تكاليف، إن وُجدت. لإيقاف تشغيل الموارد لتجنب تحمُّل الفواتير إلى ما هو أبعد من هذا البرنامج التعليمي، يمكنك حذف الموارد التي أنشأتها أو حذف المشروع. يكون مستخدمو Google Cloud الجدد مؤهَّلون للانضمام إلى برنامج فترة تجريبية مجانية بقيمة 300 دولار أمريكي.
تفعيل Cloud Shell
- من Cloud Console، انقر على تفعيل Cloud Shell .
إذا كانت هذه هي المرة الأولى التي تبدأ فيها Cloud Shell، ستظهر لك شاشة وسيطة تصف ماهيتها. إذا ظهرت لك شاشة وسيطة، انقر على متابعة.
من المفترَض أن تستغرق عملية توفير المتطلبات اللازمة والاتصال بخدمة Cloud Shell بضع دقائق فقط.
يتم تحميل هذا الجهاز الافتراضي مع جميع أدوات التطوير اللازمة. وتوفّر هذه الشبكة دليلاً رئيسيًا دائمًا بسعة 5 غيغابايت ويتم تشغيله في Google Cloud، ما يحسّن بشكل كبير من أداء الشبكة والمصادقة. يمكنك تنفيذ معظم عملك، إن لم يكن كلّه، في هذا الدرس التطبيقي حول الترميز باستخدام متصفّح.
بعد الربط بخدمة Cloud Shell، من المفترض أن تتأكّد من أنّه تمّت مصادقتك وأنّ المشروع مضبوط على رقم تعريف مشروعك.
- شغِّل الأمر التالي في Cloud Shell لتأكيد مصادقتك:
gcloud auth list
مخرجات الأمر
Credentialed Accounts ACTIVE ACCOUNT * <my_account>@<my_domain.com> To set the active account, run: $ gcloud config set account `ACCOUNT`
- شغّل الأمر التالي في Cloud Shell للتأكد من معرفة الأمر gcloud بمشروعك:
gcloud config list project
مخرجات الأمر
[core] project = <PROJECT_ID>
إذا لم يكن كذلك، يمكنك تعيينه من خلال هذا الأمر:
gcloud config set project <PROJECT_ID>
مخرجات الأمر
Updated property [core/project].
3- إعداد خدمة تخزين البيانات في السحابة الإلكترونية
في وحدة تحكم Google Cloud Platform، انتقِل إلى القائمة -> مخزن البيانات (في قسم مساحة التخزين) أو انقر هنا.
في حال لم يسبق لك استخدام Datastore في المشروع الحالي، ستظهر لك شاشة "اختيار وضع Cloud Firestore". حدِّد الخيار "وضع تخزين البيانات".
بعد ذلك، ستظهر لك شاشة "اختيار مكان تخزين بياناتك". اختَر us-east1 أو أي موقع إقليمي آخر وانقر على "إنشاء قاعدة بيانات":
4. بدء تشغيل تطبيق Java جديد لـ Spring Boot
من بيئة CloudShell، استخدِم الأمر التالي لإعداد تطبيق Spring Boot جديد وتشغيله:
$ curl https://start.spring.io/starter.tgz \ -d packaging=war \ -d dependencies=cloud-gcp \ -d type=maven-project \ -d baseDir=datastore-example \ -d bootVersion=3.0.5 | tar -xzvf -
سيؤدي هذا الإجراء إلى إنشاء دليل datastore-example/
جديد باستخدام مشروع Maven جديد، بالإضافة إلى pom.xml
وبرنامج Maven ونقطة إدخال للتطبيق.
سيوفر تطبيقنا واجهة سطر الأوامر للمستخدمين لإدخال الأوامر والاطّلاع على النتائج. سننشئ فئة لتمثيل كتاب ثم سنحفظه في Cloud Datastore باستخدام "مستودع البيانات".
نحتاج أيضًا إلى إضافة تبعية ضرورية أخرى إلى pom.xml
.
افتح "محرِّر رموز الويب" بالنقر على فتح المحرِّر من قائمة Cloud Shell.
بعد تحميل المحرّر، عدِّل ملف pom.xml
لإضافة اعتماديات Google Cloud Datastore Starter وSpring Shell Starter:
pom.xml
<project>
...
<dependencies>
...
<!-- Add GCP Datastore Starter -->
<dependency>
<groupId>com.google.cloud</groupId>
<artifactId>spring-cloud-gcp-starter-data-datastore</artifactId>
</dependency>
<!-- Add Spring Shell Starter -->
<dependency>
<groupId>org.springframework.shell</groupId>
<artifactId>spring-shell-starter</artifactId>
<version>3.0.2</version>
</dependency>
</dependencies>
</project>
5- إنشاء صف الكتاب
باستخدام المحرِّر، أنشئ الصف Book
الذي يتضمّن المحتوى التالي:
datastore-example/src/main/java/com/example/demo/Book.java
package com.example.demo;
import com.google.cloud.spring.data.datastore.core.mapping.Entity;
import org.springframework.data.annotation.Id;
@Entity(name = "books")
public class Book {
@Id
Long id;
String title;
String author;
int year;
public Book(String title, String author, int year) {
this.title = title;
this.author = author;
this.year = year;
}
public long getId() {
return this.id;
}
@Override
public String toString() {
return "Book{" +
"id=" + this.id +
", title='" + this.title + '\'' +
", author='" + this.author + '\'' +
", year=" + this.year +
'}';
}
}
كما ترى، هذا هدف بسيط. تمت إضافة تعليق توضيحي للفئة باستخدام @Entity
للإشارة إلى أنه يمكن تخزينها في Datastore وتقديم اسم النوع (يمكنك اعتبار نوع جدول في قواعد بيانات SQL، راجع الوثائق لمزيد من التفاصيل). ويكون اسم النوع اختياريًا، وإذا تم حذفه، سيتم إنشاء اسم النوع استنادًا إلى اسم الفئة.
يُرجى العِلم أنّنا أضفنا تعليقات توضيحية إلى السمة id
باستخدام @Id
. ويشير هذا إلى أننا نريد استخدام هذا الحقل كجزء المعرّف في مفتاح تخزين البيانات. يحتاج كل كيان تخزين بيانات إلى معرّف. الأنواع المتوافقة هي String
وLong
.
نلغي الطريقة toString
لجعل تمثيل السلسلة للكائنات أكثر قابلية للقراءة، سيكون ذلك مفيدًا عندما نطبعها.
6- إنشاء واجهة BookRepository
أنشِئ الصف BookRepository
باستخدام المحتوى التالي:
datastore-example/src/main/java/com/example/demo/BookRepository.java
package com.example.demo;
import java.util.List;
import com.google.cloud.spring.data.datastore.repository.DatastoreRepository;
public interface BookRepository extends DatastoreRepository<Book, Long> {
List<Book> findByAuthor(String author);
List<Book> findByYearGreaterThan(int year);
List<Book> findByAuthorAndYear(String author, int year);
}
تعمل الواجهة على توسيع DatastoreRepository<Book, Long>
حيث يكون Book
هو فئة النطاق والنوع Long
هو النوع Id
. نعلن عن ثلاث طرق لطلب البحث في مستودعنا يتم إنشاء عمليات تنفيذ لها تلقائيًا وراء الكواليس.
الْأُولَى هِيَ findByAuthor
. كما يمكنك التخمين، سيؤدي تنفيذ هذه الطريقة إلى تنفيذ طلب بحث يستخدم القيمة المقدّمة من المستخدم في فلتر الشرط لتساوي قيمة حقل المؤلف.
تنفِّذ طريقة findByYearGreaterThan
طلب بحث يعمل على فلترة حقل السنة أكبر من القيمة التي قدّمها المستخدم.
تنفِّذ findByAuthorAndYear
طلب بحث يبحث عن الكيانات التي يتطابق فيها حقلا المؤلف والسنة مع القيم التي يقدّمها المستخدم.
7. إنشاء تطبيق واجهة سطر الأوامر التفاعلي
افتح فئة التطبيق الرئيسية "DemoApplication
" وعدِّلها لتبدو على النحو التالي:
datastore-example/src/main/java/com/example/demo/DemoApplication.java
package com.example.demo;
import java.util.List;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.shell.standard.ShellComponent;
import org.springframework.shell.standard.ShellMethod;
@ShellComponent
@SpringBootApplication
public class DemoApplication {
@Autowired
BookRepository bookRepository;
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@ShellMethod("Saves a book to Cloud Datastore: save-book <title> <author> <year>")
public String saveBook(String title, String author, int year) {
Book savedBook = this.bookRepository.save(new Book(title, author, year));
return savedBook.toString();
}
@ShellMethod("Loads all books")
public String findAllBooks() {
Iterable<Book> books = this.bookRepository.findAll();
return Lists.newArrayList(books).toString();
}
@ShellMethod("Loads books by author: find-by-author <author>")
public String findByAuthor(String author) {
List<Book> books = this.bookRepository.findByAuthor(author);
return books.toString();
}
@ShellMethod("Loads books published after a given year: find-by-year-after <year>")
public String findByYearAfter(int year) {
List<Book> books = this.bookRepository.findByYearGreaterThan(year);
return books.toString();
}
@ShellMethod("Loads books by author and year: find-by-author-year <author> <year>")
public String findByAuthorYear(String author, int year) {
List<Book> books = this.bookRepository.findByAuthorAndYear(author, year);
return books.toString();
}
@ShellMethod("Removes all books")
public void removeAllBooks() {
this.bookRepository.deleteAll();
}
}
يُرجى الإشارة إلى كيفية إضافة تعليقات توضيحية إلى الصف باستخدام @ShellComponent
. وهذا يعلم Spring أننا نريد استخدام هذه الفئة كمصدر لأوامر CLI. سيتم عرض الطرق التي تحتوي على تعليقات توضيحية باستخدام @ShellMethod
على شكل أوامر CLI في تطبيقنا.
وهنا نستخدم الطرق التي أعلنّا عنها في واجهة BookRepository
: findByAuthor
وfindByYearGreaterThan
وfindByAuthorAndYear
. ونستخدم أيضًا ثلاث طرق مضمَّنة: save
وfindAll
وdeleteAll
.
لنلقِ نظرة على طريقة saveBook
. ننشئ كائن Book
باستخدام القيم التي يقدّمها المستخدم للعنوان والمؤلف والسنة. كما ترى، لا نقدّم القيمة id
، لذا سيتم تخصيصها تلقائيًا وتحديدها في الحقل id
عند الحفظ. تقبل الطريقة save
كائنًا من النوع Book
وتحفظه في "مخزن البيانات في السحابة الإلكترونية". وتعرض كائن Book
مع ملء جميع الحقول، بما في ذلك الحقل id
. وفي النهاية نرجع تمثيلاً سلسلة لهذا الكائن.
تعمل بقية الطرق بشكل مشابه: فهي تقبل تمرير المعلمات إلى طرق المستودع المناسبة وتعرض نتائج ذات سلسلة.
8. تشغيل التطبيق
لإنشاء التطبيق وبدء تشغيله، يجب أولاً التأكد من ضبط JAVA_Home على الإصدار الصحيح:
$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
نفِّذ هذا الأمر في Cloud Shell (من جذر المشروع datastore-example/
حيث يقع pom.xml
):
$ ./mvnw spring-boot:run export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64
بعد مرحلة الإنشاء الناجحة، سيظهر شعار الربيع وسيظهر طلب واجهة المستخدم على النحو التالي:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.0.5) shell:>
يمكنك الآن تجربة الأوامر التي حددناها سابقًا. للاطّلاع على قائمة الأوامر، استخدِم أمر help:
shell:> help ... find-all-books: Loads all books find-by-author: Loads books by author: find-by-author <author> find-by-author-year: Loads books by author and year: find-by-author-year <author> <year> find-by-year-after: Loads books published after a given year: find-by-year-after <year> remove-all-books: Removes all books save-book: Saves a book to Cloud Datastore: save-book <title> <author> <year>
جرّب ما يلي:
- إنشاء بضعة كتب باستخدام الأمر
save-book
- إجراء عملية بحث باستخدام الأمر
find-all-books
- البحث عن كتب للمؤلف المحدد:
find-by-author <author>
- البحث عن كتب تم نشرها بعد عام محدَّد:
find-by-year-after <year>
- البحث عن كتب للمؤلف والسنة المحدَّدين:
find-by-author-year <author> <year>
9. الاطّلاع على البيانات المخزّنة في Datastore باستخدام واجهة الويب
للاطّلاع على كيفية تخزين الكيانات في Cloud Datastore، انتقِل إلى وحدة تحكُّم Google Cloud Platform. إدخال "الكتب" في الحقل kind، إذا لزم الأمر.
10. تَنظيم
لإزالة البرامج غير المرغوب فيها، عليك إزالة جميع الكتب باستخدام الأمر "remove-all-books
" المُسمّى بشكل مناسب من هيكل التطبيق.
shell:> remove-all-books
للخروج من التطبيق، استخدِم أمر "إنهاء"، ثم على Ctrl+C
.
11. تهانينا!
أنشأت في هذا الدرس التطبيقي تطبيق CLI تفاعليًا يمكنه تخزين العناصر واستردادها من "مخزن البيانات في السحابة الإلكترونية".
مزيد من المعلومات
- تخزين البيانات في السحابة الإلكترونية: https://cloud.google.com/datastore/
- Spring Shell: https://projects.spring.io/spring-shell/
- إطلاق مشروع Google Cloud Platform: https://spring.io/projects/spring-cloud-gcp
- الانتقال إلى مستودع GitHub في Google Cloud Platform: https://github.com/GoogleCloudPlatform/spring-cloud-gcp
- Java على Google Cloud Platform: https://cloud.google.com/java/
الترخيص
هذا العمل مرخّص بموجب رخصة المشاع الإبداعي 2.0 مع نسب العمل إلى مؤلف عام.