1. نظرة عامة
Google Cloud Datastore هي قاعدة بيانات مستنِدة إلى تنسيق NoSQL ومصمَّمة لتوفير توسّع تلقائي وأداء عالٍ وسهولة تطوير التطبيقات.
ما ستتعلمه
- كيفية استخدام Cloud Datastore لحفظ واسترداد عناصر Java في 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- تهيئة Cloud Datastore
في وحدة تحكّم Google Cloud Platform، انتقِل إلى القائمة -> Datastore (في قسم "مساحة التخزين") أو انقر هنا.
إذا لم يسبق لك استخدام Datastore في المشروع الحالي، ستظهر لك شاشة "اختيار وضع Cloud Firestore". اختَر الخيار "وضع Datastore".

بعد ذلك، ستظهر لك شاشة "اختيار مكان تخزين بياناتك". اختَر 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، وواجهة Maven، ونقطة دخول التطبيق.
سيوفر تطبيقنا واجهة سطر أوامر للمستخدمين لإدخال الأوامر والاطّلاع على النتائج. سننشئ فئة لتمثيل كتاب ثم نحفظها في Cloud Datastore باستخدام Datastore Repository.
علينا أيضًا إضافة تبعية أخرى ضرورية إلى 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
باستخدام المحرّر، أنشئ الفئة 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 +
'}';
}
}
كما ترى، هذا POJO بسيط. يتم وضع تعليق توضيحي على الفئة باستخدام @Entity للإشارة إلى أنّه يمكن تخزينها في Datastore وتوفير اسم النوع (يمكنك اعتبار النوع كجدول في قواعد بيانات SQL، راجِع المستندات لمزيد من التفاصيل). اسم النوع اختياري، وفي حال حذفه، سيتم إنشاء اسم النوع استنادًا إلى اسم الفئة.
يُرجى العِلم أنّنا أضفنا تعليقًا توضيحيًا إلى السمة id باستخدام @Id. يشير ذلك إلى أنّنا نريد استخدام هذا الحقل كجزء المعرّف من مفتاح Datastore. يحتاج كل عنصر Datastore إلى معرّف. الأنواع المقبولة هي 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 بأنّنا نريد استخدام هذه الفئة كمصدر لأوامر واجهة سطر الأوامر. سيتم عرض الطرق التي تمّت إضافة التعليقات التوضيحية إليها باستخدام @ShellMethod كأوامر في واجهة سطر الأوامر في تطبيقنا.
نستخدم هنا الطرق التي حدّدناها في واجهة BookRepository: findByAuthor وfindByYearGreaterThan وfindByAuthorAndYear. نستخدم أيضًا ثلاث طرق مدمجة: save وfindAll وdeleteAll.
لنلقِ نظرة على الطريقة saveBook. ننشئ كائن Book باستخدام القيم التي يقدّمها المستخدم للعنوان والمؤلف والسنة. كما ترى، لا نقدّم قيمة id، لذا سيتم تخصيصها وتعيينها تلقائيًا في الحقل id عند الحفظ. يقبل الإجراء save عنصرًا من النوع Book ويحفظه في Cloud Datastore. تعرض هذه السمة الكائن 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 وستظهر مطالبة shell:
. ____ _ __ _ _ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \ ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \ \\/ ___)| |_)| | | | | || (_| | ) ) ) ) ' |____| .__|_| |_|_| |_\__, | / / / / =========|_|==============|___/=/_/_/_/ :: Spring Boot :: (v3.0.5) shell:>
يمكنك الآن تجربة الأوامر التي حدّدناها سابقًا. للاطّلاع على قائمة الأوامر، استخدِم أمر المساعدة:
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. أدخِل "كتب" في حقل النوع، إذا لزم الأمر.

10. تَنظيم
لإجراء عملية تنظيف، أزِل جميع الكتب باستخدام الأمر remove-all-books الذي يحمل الاسم المناسب من واجهة التطبيق.
shell:> remove-all-books
للخروج من التطبيق، استخدِم الأمر quit، ثم Ctrl+C.
11. تهانينا!
في هذا الدرس التطبيقي حول الترميز، أنشأت تطبيقًا تفاعليًا لواجهة سطر الأوامر يمكنه تخزين العناصر واسترجاعها من Cloud Datastore.
مزيد من المعلومات
- Cloud Datastore: https://cloud.google.com/datastore/
- Spring Shell: https://projects.spring.io/spring-shell/
- مشروع Spring on GCP: https://spring.io/projects/spring-cloud-gcp
- مستودع Spring on GCP GitHub: https://github.com/GoogleCloudPlatform/spring-cloud-gcp
- Java على Google Cloud Platform: https://cloud.google.com/java/
الترخيص
يخضع هذا العمل لترخيص المشاع الإبداعي مع نسب العمل إلى مؤلفه 2.0 Generic License.