Ứng dụng Spring Boot với Cloud Spanner

1. Tổng quan

Cloud Spanner là một RDBMS có tính sẵn sàng cao, có khả năng mở rộng theo chiều ngang và có nhiều khu vực.Phòng thực hành này sẽ sử dụng một phiên bản nhỏ nhất của Cloud Spanner, nhưng đừng quên tắt phiên bản này khi bạn hoàn tất!

Kiến thức bạn sẽ học được

  • Cách sử dụng Cloud Spanner để lưu và truy xuất dữ liệu bằng Spring Boot

Bạn cần có

  • Một dự án trên Google Cloud Platform
  • Một trình duyệt, chẳng hạn như Chrome hoặc Firefox

Bạn sẽ sử dụng hướng dẫn này như thế nào?

Chỉ đọc Đọc và hoàn thành bài tập

Bạn đánh giá thế nào về trải nghiệm sử dụng các dịch vụ của Google Cloud Platform?

Người mới bắt đầu Trung cấp Thành thạo

2. Thiết lập và yêu cầu

Thiết lập môi trường theo tốc độ của riêng bạn

  1. Đăng nhập vào Cloud Console rồi tạo một dự án mới hoặc sử dụng lại một dự án hiện có. (Nếu chưa có tài khoản Gmail hoặc G Suite, bạn phải tạo một tài khoản.)

dMbN6g9RawQj_VXCSYpdYncY-DbaRzr2GbnwoV7jFf1u3avxJtmGPmKpMYgiaMH-qu80a_NJ9p2IIXFppYk8x3wyymZXavjglNLJJhuXieCem56H30hwXtd8PvXGpXJO9gEUDu3cZw

ci9Oe6PgnbNuSYlMyvbXF1JdQyiHoEgnhl4PlV_MFagm2ppzhueRkqX4eLjJllZco_2zCp0V0bpTupUSKji9KkQyWqj11pqit1K1faS1V6aFxLGQdkuzGp4rsQTan7F01iePL5DtqQ

8-tA_Lheyo8SscAVKrGii2coplQp2_D1Iosb2ViABY0UUO1A8cimXUu6Wf1R9zJIRExL5OB2j946aIiFtyKTzxDcNnuznmR45vZ2HMoK3o67jxuoUJCAnqvEX6NgPGFjCVNgASc-lg

Hãy nhớ mã dự án, một tên duy nhất trên tất cả các dự án trên Google Cloud (tên ở trên đã được sử dụng và sẽ không hoạt động đối với bạn, xin lỗi!). Sau này trong lớp học lập trình này, chúng ta sẽ gọi nó là PROJECT_ID.

  1. Tiếp theo, bạn cần bật tính năng thanh toán trong Cloud Console để sử dụng các tài nguyên của Google Cloud.

Việc thực hiện lớp học lập trình này sẽ không tốn nhiều chi phí, nếu có. Hãy nhớ làm theo mọi hướng dẫn trong phần "Dọn dẹp" để biết cách tắt các tài nguyên nhằm tránh bị tính phí ngoài phạm vi hướng dẫn này. Người dùng mới của Google Cloud đủ điều kiện tham gia chương trình Dùng thử miễn phí trị giá 300 USD.

Kích hoạt Cloud Shell

  1. Trong Cloud Console, hãy nhấp vào Kích hoạt Cloud Shell H7JlbhKGHITmsxhQIcLwoe5HXZMhDlYue4K-SPszMxUxDjIeWfOHBfxDHYpmLQTzUmQ7Xx8o6OJUlANnQF0iBuUyfp1RzVad_4nCa0Zz5LtwBlUZFXFCWFrmrWZLqg1MkZz2LdgUDQ.

zlNW0HehB_AFW1qZ4AyebSQUdWm95n7TbnOr7UVm3j9dFcg6oWApJRlC0jnU1Mvb-IQp-trP1Px8xKNwt6o3pP6fyih947sEhOFI4IRF0W7WZk6hFqZDUGXQQXrw21GuMm2ecHrbzQ

Nếu chưa từng khởi động Cloud Shell, bạn sẽ thấy một màn hình trung gian (bên dưới phần hiển thị đầu tiên) mô tả về Cloud Shell. Nếu vậy, hãy nhấp vào Tiếp tục (và bạn sẽ không bao giờ thấy màn hình này nữa). Sau đây là giao diện của màn hình xuất hiện một lần:

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

Quá trình cung cấp và kết nối với Cloud Shell chỉ mất vài giây.

pTv5mEKzWMWp5VBrg2eGcuRPv9dLInPToS-mohlrqDASyYGWnZ_SwE-MzOWHe76ZdCSmw0kgWogSJv27lrQE8pvA5OD6P1I47nz8vrAdK7yR1NseZKJvcxAZrPb8wRxoqyTpD-gbhA

Máy ảo này được trang bị tất cả các công cụ phát triển mà bạn cần. Nền tảng này cung cấp một thư mục chính có dung lượng 5 GB và chạy trong Google Cloud, giúp tăng cường đáng kể hiệu suất mạng và hoạt động xác thực. Bạn có thể thực hiện hầu hết, nếu không muốn nói là tất cả, công việc trong lớp học lập trình này chỉ bằng một trình duyệt hoặc Chromebook.

Sau khi kết nối với Cloud Shell, bạn sẽ thấy rằng mình đã được xác thực và dự án đã được đặt thành mã dự án của bạn.

  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng bạn đã được xác thực:
gcloud auth list

Đầu ra của lệnh

 Credentialed Accounts
ACTIVE  ACCOUNT
*       <my_account>@<my_domain.com>

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
gcloud config list project

Đầu ra của lệnh

[core]
project = <PROJECT_ID>

Nếu không, bạn có thể đặt nó bằng lệnh sau:

gcloud config set project <PROJECT_ID>

Đầu ra của lệnh

Updated property [core/project].

3. Khởi chạy Cloud Spanner

Bật API Cloud Spanner bằng gcloud CLI:

gcloud services enable spanner.googleapis.com

Tạo một phiên bản Cloud Spanner:

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

Tạo cơ sở dữ liệu trong phiên bản:

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

Tạo tệp schema.ddl để mô tả giản đồ dữ liệu:

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

Áp dụng giản đồ cho cơ sở dữ liệu Cloud Spanner:

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

4. Khởi động một Ứng dụng Java Spring Boot mới

Trong môi trường Cloud Shell, hãy dùng lệnh sau để khởi động và khởi động một ứng dụng Spring Boot mới:

$ 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

Thao tác này sẽ tạo một thư mục spanner-example/ mới có dự án Maven mới, cùng với pom.xml của Maven, một trình bao bọc Maven, cũng như một điểm truy cập ứng dụng.

Trong tệp pom.xml, hãy thêm trình khởi động 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>

Trong application.properties, hãy định cấu hình thông tin kết nối cơ sở dữ liệu Spanner:

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

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

Đảm bảo bạn đặt JAVA_HOME thành phiên bản phù hợp:

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

Tạo lại ứng dụng để đảm bảo cấu hình Maven của bạn là chính xác:

./mvnw package

5. Tạo các thực thể

Với sự hỗ trợ Spring Data Spanner của Spring Cloud GCP, bạn có thể dễ dàng tạo một đối tượng Java và ánh xạ ORM theo thành ngữ đến một bảng Spanner bằng Spring Data.

Trước tiên, hãy tạo một lớp Mục đơn đặt hàng.

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;
}

Đối với mối quan hệ Mẹ/Con trong Spanner, bạn nên sử dụng khoá chính kết hợp. Trong ví dụ này, khoá kết hợp là order_idorder_item_id.

Tiếp theo, hãy tạo một lớp Đặt hàng:

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;
}

Lớp này sử dụng chú thích @Interleaved để tạo mối quan hệ một với nhiều với các Mặt hàng trong đơn đặt hàng.

6. Tạo giao diện OrderRepository

Tạo lớp OrderRepository có nội dung sau:

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> {
}

Giao diện này mở rộng SpannerRepository<Order, String>, trong đó Order là lớp miền và String là loại Khoá chính. Spring Data sẽ tự động cung cấp quyền truy cập CRUD thông qua giao diện này và bạn sẽ không cần tạo thêm mã nào.

7. Tạo một Trình kiểm soát REST cho các thao tác cơ bản

Mở lớp ứng dụng chính DemoApplication và sửa đổi để có dạng như sau:

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. Chạy ứng dụng

Tạo lại và chạy ứng dụng!

./mvnw spring-boot:run

Thao tác này sẽ bắt đầu đúng cách và lắng nghe trên cổng 8080.

Bạn có thể đăng bản ghi Đơn đặt hàng lên điểm cuối:

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

Nền tảng này sẽ phản hồi bằng UUID của Đơn đặt hàng.

Sau đó, bạn có thể truy xuất Đơn đặt hàng bằng UUID:

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

Để xem dữ liệu được lưu trữ như thế nào trên Cloud Spanner, hãy truy cập vào Cloud Console rồi chuyển đến Spanner → Spanner Instance → order database → orders table → Data (Spanner → Phiên bản Spanner → cơ sở dữ liệu đơn đặt hàng → bảng đơn đặt hàng → Dữ liệu).

780f4947e4a864f6.png

9. Dọn dẹp

Để dọn dẹp, hãy xoá phiên bản Spanner để phiên bản này không còn phát sinh phí nữa!

gcloud spanner instances delete spanner-instance -q

10. Xin chúc mừng!

Trong lớp học lập trình này, bạn đã tạo một ứng dụng CLI có thể tương tác, có thể lưu trữ và truy xuất dữ liệu từ Cloud Spanner!

Tìm hiểu thêm

Giấy phép

Tác phẩm này được cấp phép theo giấy phép Ghi công theo Creative Commons 2.0 Chung.