Datastore mit Java für die App Engine-Standardumgebung verwenden

In diesem Teil der Bookshelf-Anleitung für Java wird gezeigt, wie strukturierte Daten im Datastore erstellt, gelesen, aktualisiert und gelöscht werden.

Diese Seite ist Teil einer mehrseitigen Anleitung. Wenn Sie dieses Beispiel von Beginn an durcharbeiten möchten, rufen Sie die Java Bookshelf-Anwendung auf und lesen Sie die Anleitung zur Einrichtung.

Einstellungen konfigurieren

Die Datei pom.xml enthält Konfigurationsinformationen für alle Teile der Bookshelf-Anleitung. In diesem Teil der Anleitung müssen Sie keine Konfigurationsdaten hinzufügen. Die einzige Voraussetzung ist, dass die Eigenschaft bookshelf.storageType auf datastore gesetzt ist, was bereits für Sie erledigt ist.

App auf lokalem Computer ausführen

So führen Sie die App lokal aus:

  1. Geben Sie im Verzeichnis getting-started-java/bookshelf-standard/2-structured-data den folgenden Befehl ein, um einen lokalen Webserver zu starten:

    mvn package appengine:run
  2. Rufen Sie in Ihrem Webbrowser http://localhost:8080/ auf.

Sie können jetzt auf den Webseiten der Anwendung im Browser stöbern, um Bücher hinzuzufügen, zu bearbeiten und zu löschen.

App in der App Engine-Standardumgebung bereitstellen

So stellen Sie die App in der App Engine-Standardumgebung bereit:

  1. Um einen Datenspeicherindex zu erstellen, der in die Bookshelf-App hochgeladen wird, erstellen Sie mindestens ein Buch und klicken Sie dann auf Meine Bücher. Beachten Sie, dass beim Erstellen der App mit dem Befehl clean dieser lokale Index gelöscht wird. Führen Sie dies also beim Erstellen der App aus, die Sie bereitstellen möchten.
  2. Geben Sie im Verzeichnis getting-started-java/bookshelf-standard/2-structured-data den folgenden Befehl ein, um die App bereitzustellen:
    mvn appengine:deploy -Dappengine.appId=[YOUR-PROJECT-ID] -Dappengine.version=[YOUR-VERSION]
    Ersetzen Sie [YOUR-PROJECT-ID] durch Ihre Projekt-ID und [YOUR-VERSION] durch Ihre Version (zum Beispiel 1 oder 2) oder einen anderen zu verwendenden Stringwert.
  3. Geben Sie im Webbrowser die folgende URL ein:

    https://PROJECT_ID.REGION_ID.r.appspot.com

    Ersetzen Sie Folgendes:

Nachdem Sie Ihre App aktualisiert haben, können Sie die aktualisierte Version noch einmal bereitstellen. Geben Sie dazu denselben Befehl wie bei der ersten Bereitstellung der App ein und dieselbe Projekt-ID und Version an. Dadurch wird die aktuell bereitgestellte App überschrieben. Wenn Sie in der aktualisierten Befehlszeile eine andere Versionszeichenfolge angeben, erstellt die neue Bereitstellung eine neue Version Ihrer App und befördert sie zur aktuell bereitgestellten Version.

Sie können die Kosten senken, indem Sie die nicht standardmäßigen Versionen der App löschen.

So löschen Sie eine Anwendungsversion:

  1. Rufen Sie in der Cloud Console die Seite Versionen für App Engine auf.

    Zur Seite "Versionen"

  2. Klicken Sie auf das Kästchen für die nicht standardmäßige App-Version, die Sie löschen möchten.
  3. Klicken Sie auf Löschen , um die Anwendungsversion zu löschen.

Ausführliche Informationen zum Bereinigen kostenpflichtiger Ressourcen finden Sie im letzten Schritt dieser Anleitung im Abschnitt Bereinigen.

App-Struktur

Das folgende Diagramm zeigt die Komponenten der Anwendung und deren Zusammenwirken.

Bookshelf app deployment process and structure

Code verstehen

In diesem Abschnitt werden der App-Code und dessen Funktionsweise erläutert.

Mit Datastore interagieren

Die App verwendet ein autorisiertes Datastore-Dienstobjekt, um mit Datastore zu interagieren. Dieses Objekt tauscht Anmeldeinformationen gegen ein Token aus, um auf die Datastore APIs zuzugreifen. Die App erstellt auch ein KeyFactory Objekt vom Typ Book. Das Buch ist die einzige Art von Daten, die diese App speichert. Im Allgemeinen können Sie jedoch so viele Datentypen speichern, wie Sie möchten. Datastore unterstützt eine umfangreiche Auswahl von Datentypen.

private DatastoreService datastore;
private static final String BOOK_KIND = "Book2";

public DatastoreDao() {
  datastore = DatastoreServiceFactory.getDatastoreService(); // Authorized Datastore service
}

Bücher erstellen

Ein Buch wird von der App als Entität in Datastore gespeichert. Eine Entität besteht aus einem Schlüssel und einer Sammlung von Name/Wert-Paaren. Die Methode createBook erstellt eine neue Entität vom Typ BOOK und setzt die vom Nutzer angegebenen Werte für Autor, Beschreibung, Veröffentlichungsdatum und Titel ein. Der Schlüssel wird der Entität zugewiesen, wenn die Entität zu Datastore hinzugefügt wird.

@Override
public Long createBook(Book book) {
  Entity incBookEntity = new Entity(BOOK_KIND);  // Key will be assigned once written
  incBookEntity.setProperty(Book.AUTHOR, book.getAuthor());
  incBookEntity.setProperty(Book.DESCRIPTION, book.getDescription());
  incBookEntity.setProperty(Book.PUBLISHED_DATE, book.getPublishedDate());
  incBookEntity.setProperty(Book.TITLE, book.getTitle());

  Key bookKey = datastore.put(incBookEntity); // Save the Entity
  return bookKey.getId();                     // The ID of the Key
}

Aus Datastore lesen

Die Methode readBook wandelt eine Buch-ID in einen Schlüssel um. Anschließend wird der Schlüssel an die Methode getProperty übergeben, die ein Entity-Objekt zurückgibt.

@Override
public Book readBook(Long bookId) {
  try {
    Entity bookEntity = datastore.get(KeyFactory.createKey(BOOK_KIND, bookId));
    return entityToBook(bookEntity);
  } catch (EntityNotFoundException e) {
    return null;
  }
}

Die Methode entityToBook konvertiert die von Datastore zurückgegebene Entität in ein Book-Objekt. Dazu werden für jeden Typ getProperty-Methoden verwendet, ähnlich wie setProperty bei der Entitätserstellung verwendet wird. Eigenschaftsnamen sind String-Werte.

public Book entityToBook(Entity entity) {
  return new Book.Builder()                                     // Convert to Book form
      .author((String) entity.getProperty(Book.AUTHOR))
      .description((String) entity.getProperty(Book.DESCRIPTION))
      .id(entity.getKey().getId())
      .publishedDate((String) entity.getProperty(Book.PUBLISHED_DATE))
      .title((String) entity.getProperty(Book.TITLE))
      .build();
}

Bücher aktualisieren

Zum Aktualisieren muss die Methode put mit einem Entity aufgerufen werden.

@Override
public void updateBook(Book book) {
  Key key = KeyFactory.createKey(BOOK_KIND, book.getId());  // From a book, create a Key
  Entity entity = new Entity(key);         // Convert Book to an Entity
  entity.setProperty(Book.AUTHOR, book.getAuthor());
  entity.setProperty(Book.DESCRIPTION, book.getDescription());
  entity.setProperty(Book.PUBLISHED_DATE, book.getPublishedDate());
  entity.setProperty(Book.TITLE, book.getTitle());

  datastore.put(entity);                   // Update the Entity
}

Bücher löschen

Zum Löschen mit Datastore muss die Methode delete mit einem Key aufgerufen werden.

@Override
public void deleteBook(Long bookId) {
  Key key = KeyFactory.createKey(BOOK_KIND, bookId);        // Create the Key
  datastore.delete(key);                      // Delete the Entity
}

Bücher auflisten

Die Methode listBooks gibt eine Liste von 10 Büchern gleichzeitig zusammen mit einer URL-sicheren Cursor zurück.

@Override
public Result<Book> listBooks(String startCursorString) {
  FetchOptions fetchOptions = FetchOptions.Builder.withLimit(10); // Only show 10 at a time
  if (startCursorString != null && !startCursorString.equals("")) {
    fetchOptions.startCursor(Cursor.fromWebSafeString(startCursorString)); // Where we left off
  }
  Query query = new Query(BOOK_KIND) // We only care about Books
      .addSort(Book.TITLE, SortDirection.ASCENDING); // Use default Index "title"
  PreparedQuery preparedQuery = datastore.prepare(query);
  QueryResultIterator<Entity> results = preparedQuery.asQueryResultIterator(fetchOptions);

  List<Book> resultBooks = entitiesToBooks(results);     // Retrieve and convert Entities
  Cursor cursor = results.getCursor();              // Where to start next time
  if (cursor != null && resultBooks.size() == 10) {         // Are we paging? Save Cursor
    String cursorString = cursor.toWebSafeString();               // Cursors are WebSafe
    return new Result<>(resultBooks, cursorString);
  } else {
    return new Result<>(resultBooks);
  }
}

Index

Datastore erstellt standardmäßig einen Index für jedes Ihrer Attribute, obwohl Sie dieses Verhalten ändern können. Einige Abfragen benötigen mehr als ein einzelnes Attribut im Index, z. B. die obigen Abfragen Query by user und ordered by Title. Um derartige Abfragen zu unterstützen, können Sie Indexe manuell oder mithilfe des Entwicklungsservers erstellen.