تطبيق Spring Boot مع Cloud Spanner

1. نظرة عامة

إنّ Cloud Spanner هو نظام RDBMS متوفّر بشكل كبير وقابل للتطور أفقيًا ومتعدد المناطق. سيستخدم مختبر الترميز هذا أصغر مثيل من Cloud Spanner، ولكن لا تنسَ إيقاف الخدمة عند الانتهاء.

المعلومات التي ستطّلع عليها

  • كيفية استخدام Cloud Spanner لحفظ البيانات واستردادها باستخدام Spring Boot

المتطلبات

  • مشروع Google Cloud Platform
  • متصفح، مثل Chrome أو Firefox

كيف ستستخدم هذا البرنامج التعليمي؟

القراءة فقط اقرأها وأكمِل التمارين

ما هو تقييمك لتجربتك في استخدام خدمات Google Cloud Platform؟

حديث متوسط بارع

2. الإعداد والمتطلبات

إعداد بيئة ذاتية

  1. سجِّل الدخول إلى Cloud Console وأنشِئ مشروعًا جديدًا أو أعِد استخدام مشروع حالي. (إذا لم يكن لديك حساب على Gmail أو G Suite، عليك إنشاء حساب.)

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

يُرجى تذكُّر رقم تعريف المشروع، وهو اسم فريد في جميع مشاريع Google Cloud (سبق أن تم استخدام الاسم أعلاه ولن يكون مناسبًا لك). ستتم الإشارة إليها لاحقًا في هذا الدرس التطبيقي حول الترميز باسم PROJECT_ID.

  1. بعد ذلك، عليك تفعيل الفوترة في Cloud Console لاستخدام موارد Google Cloud.

إنّ تنفيذ هذا الدرس التطبيقي حول الترميز لن يكون مكلفًا أو مكلفًا على الإطلاق. احرص على اتّباع أي تعليمات في قسم "الحذف سريعًا". الذي يقدم لك نصائح حول كيفية إيقاف تشغيل الموارد حتى لا تتكبّد أي فواتير خارج نطاق هذا البرنامج التعليمي. يكون مستخدمو Google Cloud الجدد مؤهَّلون للانضمام إلى برنامج الفترة التجريبية المجانية التي تبلغ قيمتها 300 دولار أمريكي.

تفعيل Cloud Shell

  1. من Cloud Console، انقر على تفعيل Cloud Shell H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RzVad_4nCa0Zz5LtwBlUZFXFCWFrmrWZLqg1MkZz2LdgUDQ.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

إذا لم يسبق لك بدء تشغيل Cloud Shell، ستظهر لك شاشة وسيطة (الجزء السفلي غير المرئي من الصفحة) تصف ماهيتها. وفي هذه الحالة، انقر على متابعة (ولن تظهر لك مرة أخرى). إليك ما تبدو عليه هذه الشاشة التي تُستخدم لمرة واحدة:

kEPbNAo_w5C_pi9QvhFwWwky1cX8hr_xEMGWySNIoMCdi-Djx9AQRqWn-__DmEpC7vKgUtl-feTcv-wBxJ8NwzzAp7mY65-fi2LJo4twUoewT1SUjd6Y3h81RG3rKIkqhoVlFR-G7w

من المفترَض أن تستغرق عملية توفير المتطلبات اللازمة والاتصال بخدمة Cloud Shell بضع دقائق فقط.

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

يتم تحميل هذه الآلة الافتراضية مزوّدة بكل أدوات التطوير التي ستحتاج إليها. وتوفّر هذه الشبكة دليلاً رئيسيًا دائمًا بسعة 5 غيغابايت ويتم تشغيله في Google Cloud، ما يحسّن بشكل كبير من أداء الشبكة والمصادقة. يمكنك تنفيذ معظم عملك، إن لم يكن كلّه، في هذا الدرس التطبيقي حول الترميز باستخدام متصفّح أو جهاز Chromebook.

بعد الربط بخدمة Cloud Shell، من المفترض أن يظهر لك أنّه قد تمت مصادقتك وأنّ المشروع معيّن سبق أن تم ضبطه على رقم تعريف مشروعك.

  1. شغِّل الأمر التالي في 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`
gcloud config list project

مخرجات الأمر

[core]
project = <PROJECT_ID>

إذا لم يكن كذلك، يمكنك تعيينه من خلال هذا الأمر:

gcloud config set project <PROJECT_ID>

مخرجات الأمر

Updated property [core/project].

3- إعداد Cloud Spanner

تفعيل واجهة برمجة تطبيقات Cloud Spanner باستخدام gcloud CLI:

gcloud services enable spanner.googleapis.com

إنشاء مثيل Cloud Spanner:

gcloud spanner instances create spanner-instance \
 --config=regional-us-central1 \
 --nodes=1 --description="A Spanner Instance"

أنشئ قاعدة بيانات داخل المثيل:

gcloud spanner databases create orders \
  --instance=spanner-instance

أنشئ ملف schema.ddl لوصف مخطط البيانات:

cat << EOF > schema.ddl
CREATE TABLE orders (
  order_id STRING(36) NOT NULL,
  description STRING(255),
  creation_timestamp TIMESTAMP,
) PRIMARY KEY (order_id);

CREATE TABLE order_items (
  order_id STRING(36) NOT NULL,
  order_item_id STRING(36) NOT NULL,
  description STRING(255),
  quantity INT64,
) PRIMARY KEY (order_id, order_item_id),
  INTERLEAVE IN PARENT orders ON DELETE CASCADE;
EOF

طبِّق المخطط على قاعدة بيانات Cloud Spanner:

gcloud spanner databases ddl update orders \
  --instance=spanner-instance \
  --ddl="$(<schema.ddl)"

4. بدء تشغيل تطبيق Java جديد لـ Spring Boot

من بيئة Cloud Shell، استخدم الأمر التالي لإعداد تطبيق Spring Boot جديد وإطلاقه:

$ curl https://start.spring.io/starter.tgz \
  -d packaging=jar \
  -d dependencies=cloud-gcp,web,lombok \
  -d baseDir=spanner-example \
  -d type=maven-project \
  -d bootVersion=3.2.6 | tar -xzvf -

$ cd spanner-example

سيؤدي ذلك إلى إنشاء دليل spanner-example/ جديد باستخدام مشروع Maven جديد، بالإضافة إلى برنامج Maven (pom.xml)، وهو برنامج تضمين Maven، بالإضافة إلى نقطة إدخال للتطبيق.

في ملف pom.xml، أضِف إجراء تفعيل Spring Data Cloud Spanner.

spanner-example/pom.xml

<project>
  ...
  <dependencies>
        ...
        <!-- Add Spring Cloud GCP Spanner Starter -->
        <dependency>
                <groupId>com.google.cloud</groupId>
                <artifactId>spring-cloud-gcp-starter-data-spanner</artifactId>
        </dependency>

        ...

  </dependencies>

  ...
</project>

في application.property، اضبط معلومات اتصال قاعدة بيانات Spanner:

spanner-example/src/main/resources/application.properties

spring.cloud.gcp.spanner.instance-id=spanner-instance
spring.cloud.gcp.spanner.database=orders

تأكَّد من ضبط JAVA_HOME على الإصدار الصحيح:

export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64/

أعِد إنشاء التطبيق للتأكّد من صحة إعدادات Maven:

./mvnw package

5- إنشاء الكيانات

من خلال دعم Spring Data Spanner من Spring Cloud GCP، يمكنك بسهولة إنشاء كائن Java وربط ORM المجهول بجدول Spanner، باستخدام بيانات Spring.

أولاً، قم بإنشاء فئة Order Item (عنصر الطلب).

spanner-example/src/main/java/com/example/demo/OrderItem.java

package com.example.demo;

import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;

@Table(name="order_items")
@Data
class OrderItem {
  @PrimaryKey(keyOrder = 1)
  @Column(name="order_id")
  private String orderId;

  @PrimaryKey(keyOrder = 2)
  @Column(name="order_item_id")
  private String orderItemId;

  private String description;
  private Long quantity;
}

بالنسبة إلى علاقات الأصل/التابع في Spanner، يجب عليك استخدام مفتاح أساسي مركب. في هذا المثال، المفتاح المركب هو order_id وorder_item_id.

بعد ذلك، أنشئ فئة طلب:

spanner-example/src/main/java/com/example/demo/Order.java

package com.example.demo;

import java.time.LocalDateTime;
import java.util.List;
import lombok.Data;
import com.google.cloud.spring.data.spanner.core.mapping.Column;
import com.google.cloud.spring.data.spanner.core.mapping.Interleaved;
import com.google.cloud.spring.data.spanner.core.mapping.PrimaryKey;
import com.google.cloud.spring.data.spanner.core.mapping.Table;

@Table(name="orders")
@Data
public class Order {
  @PrimaryKey
  @Column(name="order_id")
  private String id;

  private String description;

  @Column(name="creation_timestamp")
  private LocalDateTime timestamp;

  @Interleaved
  private List<OrderItem> items;
}

تستخدم هذه الفئة التعليق التوضيحي @Interleaved لإنشاء علاقة واحد إلى العديد من العناصر.

6- إنشاء واجهة OrderRepository

أنشِئ الصف OrderRepository باستخدام المحتوى التالي:

spanner-example/src/main/java/com/example/demo/OrderRepository.java

package com.example.demo;

import com.google.cloud.spring.data.spanner.repository.SpannerRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface OrderRepository extends SpannerRepository<Order, String> {
}

تعمل الواجهة على توسيع SpannerRepository<Order, String> حيث Order هو فئة النطاق وString هو نوع المفتاح الأساسي. ستوفّر Spring Data إمكانية الوصول إلى CRUD من خلال هذه الواجهة تلقائيًا ولن تحتاج إلى إنشاء أي رمز إضافي.

7. إنشاء وحدة تحكم REST للعمليات الأساسية

افتح فئة التطبيق الرئيسية "DemoApplication" وعدِّلها لتبدو على النحو التالي:

spanner-example/src/main/java/com/example/demo/DemoApplication.java

package com.example.demo;

import java.time.LocalDateTime;
import java.util.UUID;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.server.ResponseStatusException;

@SpringBootApplication
public class DemoApplication {
        public static void main(String[] args) {
                SpringApplication.run(DemoApplication.class, args);
        }
}

@RestController
class OrderController {
  private final OrderRepository orderRepository;

        OrderController(OrderRepository orderRepository) {
                this.orderRepository = orderRepository;
        }

        @GetMapping("/api/orders/{id}")
        public Order getOrder(@PathVariable String id) {
          return orderRepository.findById(id)
                                .orElseThrow(() -> new ResponseStatusException(HttpStatus.NOT_FOUND, id + " not found"));
        }

        @PostMapping("/api/orders")
        public String createOrder(@RequestBody Order order) {
                // Spanner currently does not auto generate IDs
                // Generate UUID on new orders
                order.setId(UUID.randomUUID().toString());
                order.setTimestamp(LocalDateTime.now());

                order.getItems().forEach(item -> {
                        // Assign parent ID, and also generate child ID
                        item.setOrderId(order.getId());
                        item.setOrderItemId(UUID.randomUUID().toString());
                });

          Order saved = orderRepository.save(order);
          return saved.getId();
        }
}

8. تشغيل التطبيق

إعادة إنشاء التطبيق وتشغيله!

./mvnw spring-boot:run

من المفترض أن يبدأ الإرسال بشكل صحيح ويتم توصيله عبر المنفذ 8080.

يمكنك نشر سجلّ طلب في نقطة النهاية:

curl -H"Content-Type: application/json" -d'{"description": "My orders", "items": [{"description": "Android Phone", "quantity": "1"}]}' \
  http://localhost:8080/api/orders

من المفترض أن يتم الردّ باستخدام UUID للطلب.

يمكنك بعد ذلك استرداد "الطلب" باستخدام UUID:

curl http://localhost:8080/api/orders/REPLACE_WITH_ORDER_UUID

للاطّلاع على كيفية تخزين البيانات في Cloud Spanner، انتقِل إلى Cloud Console وانتقِل إلى Spanner ← مثيل Spanner ← قاعدة بيانات الطلبات ← جدول الطلبات ← البيانات.

780f4947e4a864f6.png

9. تَنظيم

لإزالة هذا المحتوى، احذف مثيل Spanner كي لا يتحمّل أي رسوم بعد الآن.

gcloud spanner instances delete spanner-instance -q

10. تهانينا!

وفي هذا الدرس التطبيقي حول الترميز، أنشأت تطبيق CLI تفاعليًا يمكنه تخزين البيانات واستردادها من Cloud Spanner.

مزيد من المعلومات

الترخيص

هذا العمل مرخّص بموجب رخصة المشاع الإبداعي 2.0 مع نسب العمل إلى مؤلف عام.