Aplikacja Spring Boot korzystająca z Cloud Datastore

1. Przegląd

Google Cloud Datastore to baza danych dokumentów NoSQL zaprojektowana pod kątem automatycznego skalowania, wysokiej wydajności i łatwego tworzenia aplikacji.

Czego się nauczysz

  • Jak używać Cloud Datastore do zapisywania i pobierania obiektów Java w Spring Boot

Czego potrzebujesz

  • Projekt Google Cloud Platform
  • przeglądarka, np. Chrome lub Firefox;

Jak zamierzasz korzystać z tego samouczka?

Tylko przeczytaj Przeczytaj i wykonaj ćwiczenia

Jak oceniasz korzystanie z usług Google Cloud Platform?

Początkujący Średnio zaawansowany Zaawansowany

2. Konfiguracja i wymagania

Samodzielne konfigurowanie środowiska

  1. Zaloguj się w konsoli Google Cloud i utwórz nowy projekt lub użyj istniejącego. Jeśli nie masz jeszcze konta Gmail ani Google Workspace, musisz je utworzyć.

b35bf95b8bf3d5d8.png

a99b7ace416376c4.png

bd84a6d3004737c5.png

  • Nazwa projektu to wyświetlana nazwa uczestników tego projektu. Jest to ciąg znaków, który nie jest używany przez interfejsy API Google. Zawsze możesz ją zaktualizować.
  • Identyfikator projektu jest unikalny we wszystkich projektach Google Cloud i nie można go zmienić po ustawieniu. Konsola Cloud automatycznie generuje unikalny ciąg znaków. Zwykle nie musisz się tym przejmować. W większości ćwiczeń z programowania musisz odwoływać się do identyfikatora projektu (zwykle oznaczanego jako PROJECT_ID). Jeśli wygenerowany identyfikator Ci się nie podoba, możesz wygenerować inny losowy identyfikator. Możesz też spróbować własnej nazwy i sprawdzić, czy jest dostępna. Po tym kroku nie można go zmienić i pozostaje on taki przez cały czas trwania projektu.
  • Warto wiedzieć, że istnieje też trzecia wartość, numer projektu, której używają niektóre interfejsy API. Więcej informacji o tych 3 wartościach znajdziesz w dokumentacji.
  1. Następnie musisz włączyć płatności w konsoli Cloud, aby korzystać z zasobów i interfejsów API Google Cloud. Wykonanie tego laboratorium nie będzie kosztować dużo, a może nawet nic. Aby wyłączyć zasoby i uniknąć naliczania opłat po zakończeniu tego samouczka, możesz usunąć utworzone zasoby lub projekt. Nowi użytkownicy Google Cloud mogą skorzystać z bezpłatnego okresu próbnego, w którym mają do dyspozycji środki w wysokości 300 USD.

Aktywowanie Cloud Shell

  1. W konsoli Cloud kliknij Aktywuj Cloud Shell 853e55310c205094.png.

55efc1aaa7a4d3ad.png

Jeśli uruchamiasz Cloud Shell po raz pierwszy, zobaczysz ekran pośredni z opisem tego środowiska. Jeśli pojawił się ekran pośredni, kliknij Dalej.

9c92662c6a846a5c.png

Uzyskanie dostępu do środowiska Cloud Shell i połączenie się z nim powinno zająć tylko kilka chwil.

9f0e51b578fecce5.png

Ta maszyna wirtualna zawiera wszystkie potrzebne narzędzia dla programistów. Zawiera również stały katalog domowy o pojemności 5 GB i działa w Google Cloud, co znacznie zwiększa wydajność sieci i usprawnia proces uwierzytelniania. Większość zadań w tym module, a być może wszystkie, możesz wykonać w przeglądarce.

Po połączeniu z Cloud Shell zobaczysz, że uwierzytelnianie zostało już przeprowadzone, a projekt jest już ustawiony na Twój identyfikator projektu.

  1. Aby potwierdzić, że uwierzytelnianie zostało przeprowadzone, uruchom w Cloud Shell to polecenie:
gcloud auth list

Wynik polecenia

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

To set the active account, run:
    $ gcloud config set account `ACCOUNT`
  1. Aby potwierdzić, że polecenie gcloud zna Twój projekt, uruchom w Cloud Shell to polecenie:
gcloud config list project

Wynik polecenia

[core]
project = <PROJECT_ID>

Jeśli nie, możesz go ustawić za pomocą tego polecenia:

gcloud config set project <PROJECT_ID>

Wynik polecenia

Updated property [core/project].

3. Inicjowanie Cloud Datastore

W konsoli GCP otwórz Menu –> Datastore (w sekcji Przechowywanie danych) lub kliknij tutaj.

Jeśli w bieżącym projekcie nigdy nie używasz Datastore, zobaczysz ekran „Wybierz tryb Cloud Firestore”. Wybierz opcję „Tryb Datastore”.

f938295c7ff297f4.png

Następnie zobaczysz ekran „Wybierz, gdzie chcesz zapisywać dane”. Wybierz us-east1 lub inną lokalizację regionalną i kliknij „Utwórz bazę danych”:

916ac84fec10fae7.png

4. Wczytywanie nowej aplikacji Spring Boot w Javie

W środowisku Cloud Shell użyj tego polecenia, aby zainicjować i uruchomić nową aplikację 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 -

Spowoduje to utworzenie nowego katalogu datastore-example/ z nowym projektem Maven, a także pom.xml Maven, otoki Maven i punktu wejścia aplikacji.

Nasza aplikacja będzie udostępniać interfejs wiersza poleceń, w którym użytkownicy będą mogli wpisywać polecenia i wyświetlać wyniki. Utworzymy klasę reprezentującą książkę, a następnie zapiszemy ją w Cloud Datastore za pomocą repozytorium Datastore.

Musimy też dodać jeszcze jedną niezbędną zależność do pliku pom.xml.

Otwórz edytor kodu internetowego, klikając Otwórz edytor w menu Cloud Shell.

6d823258c76a7452.png

Po wczytaniu edytora zmodyfikuj plik pom.xml, aby dodać zależności Google Cloud Datastore Starter i 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. Tworzenie klasy Book

W edytorze utwórz klasę Book o tej treści:

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

Jak widać, jest to prosty obiekt POJO. Klasa jest oznaczona adnotacją @Entity, aby wskazać, że można ją przechowywać w Datastore i podawać nazwę rodzaju (rodzaj można traktować jako tabelę w bazach danych SQL; więcej informacji znajdziesz w dokumentacji). Nazwa rodzaju jest opcjonalna. Jeśli ją pominiesz, zostanie wygenerowana na podstawie nazwy klasy.

Zauważ, że właściwość id została opatrzona adnotacją @Id. Oznacza to, że chcemy, aby to pole było używane jako część identyfikatora klucza Datastore. Każdy obiekt Datastore musi mieć identyfikator. Obsługiwane typy to StringLong.

Zastępujemy metodę toString, aby ciąg znaków reprezentujący obiekty był bardziej czytelny. Będzie to przydatne podczas ich drukowania.

6. Tworzenie interfejsu BookRepository

Utwórz klasę BookRepository z tą treścią:

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

Interfejs rozszerza DatastoreRepository<Book, Long>, gdzie Book to klasa domeny, a Long to typ Id. W naszym repozytorium deklarujemy 3 metody zapytań, dla których implementacje są generowane automatycznie w tle.

Pierwszy to findByAuthor. Jak można się domyślić, implementacja tej metody spowoduje wykonanie zapytania, które będzie używać wartości podanej przez użytkownika w filtrze warunku równości z polem autora.

Metoda findByYearGreaterThan wykonuje zapytanie, które filtruje pole roku, aby uzyskać wartości większe niż podana przez użytkownika.

findByAuthorAndYear wykonuje zapytanie, które wyszukuje jednostki, w których pola autora i roku pasują do wartości podanych przez użytkownika.

7. Tworzenie interaktywnej aplikacji CLI

Otwórz główną klasę aplikacji DemoApplication i zmodyfikuj ją tak, aby wyglądała tak:

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

Zwróć uwagę, jak oznaczyliśmy klasę symbolem @ShellComponent. Informuje to Springa, że chcemy użyć tej klasy jako źródła poleceń interfejsu wiersza poleceń. Metody oznaczone symbolem @ShellMethod będą dostępne w naszej aplikacji jako polecenia interfejsu wiersza poleceń.

Używamy tu metod zadeklarowanych w interfejsie BookRepository: findByAuthor, findByYearGreaterThan, findByAuthorAndYear. Używamy też 3 wbudowanych metod: save, findAlldeleteAll.

Przyjrzyjmy się metodzie saveBook. Tworzymy obiekt Book, używając podanych przez użytkownika wartości tytułu, autora i roku. Jak widać, nie podajemy wartości id, więc zostanie ona automatycznie przydzielona i przypisana do pola id podczas zapisywania. Metoda save akceptuje obiekt typu Book i zapisuje go w Cloud Datastore. Zwraca obiekt Book ze wszystkimi wypełnionymi polami, w tym polem id. Na koniec zwracamy ciąg znaków reprezentujący ten obiekt.

Pozostałe metody działają podobnie: przyjmują przekazane parametry do odpowiednich metod repozytorium i zwracają wyniki w postaci ciągów znaków.

8. Uruchamianie aplikacji

Aby skompilować i uruchomić aplikację, najpierw sprawdź, czy zmienna JAVA_HOME jest ustawiona na właściwą wersję:

$ export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

Uruchom to polecenie w Cloud Shell (w katalogu głównym projektu datastore-example/, w którym znajduje się plik pom.xml):

$ ./mvnw spring-boot:run
export JAVA_HOME=/usr/lib/jvm/java-1.17.0-openjdk-amd64

Po pomyślnym zakończeniu etapu kompilacji pojawi się logo Springa i wiersz poleceń powłoki:

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::                (v3.0.5)



shell:>

Teraz możesz wypróbować zdefiniowane wcześniej polecenia. Aby wyświetlić listę poleceń, użyj polecenia pomocy:

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>

Wykonaj te czynności:

  1. Utwórz kilka książek za pomocą polecenia save-book.
  2. Przeprowadzanie wyszukiwania za pomocą polecenia find-all-books
  3. Znajdź książki konkretnego autora: find-by-author <author>
  4. Znajdź książki opublikowane po określonym roku: find-by-year-after <year>
  5. Znajdź książki konkretnego autora z określonego roku: find-by-author-year <author> <year>

9. Sprawdzanie, co jest przechowywane w Datastore, za pomocą interfejsu internetowego

Aby zobaczyć, jak encje są przechowywane w Cloud Datastore, otwórz konsolę GCP. W razie potrzeby wpisz „books” w polu „kind”.

5fab21a6c89f45a.png

10. Czyszczenie danych

Aby zwolnić miejsce, usuń wszystkie książki za pomocą polecenia remove-all-books w powłoce aplikacji.

shell:> remove-all-books

Aby zamknąć aplikację, użyj polecenia quit, a następnie Ctrl+C.

11. Gratulacje!

W tym module stworzyliśmy interaktywną aplikację CLI, która może przechowywać i pobierać obiekty z Cloud Datastore.

Więcej informacji

Licencja

To zadanie jest licencjonowane na podstawie ogólnej licencji Creative Commons Attribution 2.0.