Entitäten, Attribute und Schlüssel

Datenobjekte in Cloud Datastore werden als Entitäten bezeichnet. Eine Entität verfügt über ein oder mehrere benannte Attribute, von denen jedes einen oder mehrere Werte haben kann. Entitäten derselben Art müssen nicht dieselben Attribute haben und die Werte der Entitäten für ein bestimmtes Attribut müssen nicht alle denselben Datentyp haben. Falls erforderlich, kann eine Anwendung derartige Einschränkungen in einem eigenen Datenmodell festlegen und durchsetzen.

Datastore unterstützt viele Datentypen für Attributwerte. Diese umfassen unter anderem:

  • Ganzzahlen
  • Gleitkommazahlen
  • Strings
  • Datumsangaben
  • Binärdaten

Eine vollständige Liste der Typen finden Sie unter Attribute und Werttypen.

Jede Entität in Datastore hat einen Schlüssel, der sie eindeutig identifiziert. Der Schlüssel besteht aus den folgenden Komponenten:

  • Namespace der Entität, der die Mehrinstanzenfähigkeit ermöglicht
  • Die Art der Entität, mit der sie für Datastore-Abfragen kategorisiert wird
  • Kennung für die einzelne Entität, entweder
    • ein Schlüsselnamen-String
    • eine ganzzahlige numerische ID
  • Optionaler Ancestor-Pfad zur Entität innerhalb der Datastore-Hierarchie

Eine Anwendung kann eine einzelne Entität mithilfe des Entitätsschlüssels aus Datastore abrufen oder eine bzw. mehrere Entitäten mit einer Abfrage ermitteln, die auf den Schlüsseln oder Attributwerten der Entitäten basiert.

Das Java App Engine SDK enthält eine einfache API, die im Paket com.google.appengine.api.datastore bereitgestellt wird und die Funktionen von Datastore direkt unterstützt. Alle Beispiele in diesem Dokument basieren auf dieser Low-Level-API. Sie können sie entweder direkt in Ihrer Anwendung oder als Grundlage für die Erstellung einer eigenen Datenverwaltungsschicht verwenden.

Datastore selbst erzwingt keine Einschränkungen für die Struktur der Entitäten, beispielsweise ob ein bestimmtes Attribut einen Wert eines bestimmten Typs hat. Diese Aufgabe bleibt der Anwendung überlassen.

Arten und Kennungen

Jede Datastore-Entität ist von einer bestimmten Art. Mit dieser kann die Entität für Abfragen kategorisiert werden. In einer Personalanwendung kann beispielsweise jeder Mitarbeiter eines Unternehmens mit einer Entität der Art Employee dargestellt werden. In der Java Datastore API wird die Art einer Entität beim Erstellen als Argument für den Konstruktor Entity() angegeben. Alle Artnamen, die mit zwei Unterstrichen (__) beginnen, sind reserviert und dürfen nicht verwendet werden.

Der folgende Beispielcode erstellt eine Entität der Art Employee, gibt ihre Attributwerte an und speichert die Entität in Datastore:

Entity employee = new Entity("Employee", "asalieri");
employee.setProperty("firstName", "Antonio");
employee.setProperty("lastName", "Salieri");
employee.setProperty("hireDate", new Date());
employee.setProperty("attendedHrTraining", true);

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
datastore.put(employee);

Neben einer Art verfügt jede Entität über eine Kennung, die der Entität bei ihrer Erstellung zugewiesen wird. Weil sie zum Schlüssel der Entität gehört, ist die Kennung dauerhaft mit der Entität verknüpft und kann nicht geändert werden. Es gibt zwei Möglichkeiten der Zuweisung:

  • Die Anwendung kann ihren eigenen Schlüsselnamen-String für die Entität angeben.
  • Datastore kann der Entität automatisch eine ganzzahlige numerische ID zuweisen.

Übergeben Sie dem Konstruktor beim Erstellen der Entität den Namen als zweites Argument, um einer Entität einen Schlüsselnamen zuzuweisen:

Entity employee = new Entity("Employee", "asalieri");

Soll Cloud Datastore automatisch eine numerische ID zuweisen, lassen Sie dieses Argument weg:

Entity employee = new Entity("Employee");

Kennungen zuweisen

Datastore kann so konfiguriert werden, dass automatische IDs mithilfe von zwei verschiedenen Richtlinien für automatische IDs generiert werden:

  • Die Richtlinie default generiert eine zufällige Abfolge von bisher nicht verwendeten IDs, die näherungsweise gleichmäßig verteilt sind. Jede ID kann maximal 16 Dezimalstellen enthalten.
  • Die Richtlinie legacy erstellt eine Abfolge nicht aufeinanderfolgender IDs aus kleineren Ganzzahlen.

Wenn Sie die Entitäts-IDs für den Nutzer anzeigen möchten und/oder deren Reihenfolge wichtig ist, ist eine manuelle Zuordnung die beste Lösung.

Datastore generiert eine zufällige Abfolge von nicht verwendeten IDs, die annähernd gleichmäßig verteilt sind. Jede ID kann maximal 16 Dezimalstellen enthalten.

Vom System zugeordnete ID-Werte sind für die Entitätengruppe garantiert eindeutig. Wenn Sie eine Entität aus einer Entitätengruppe oder einem Namespace in eine andere Entitätengruppe oder einen anderen Namespace kopieren und den ID-Teil des Schlüssels beibehalten möchten, stellen Sie sicher, dass Sie die ID zuerst zuordnen, damit Datastore diese ID nicht für eine künftige Zuweisung auswählt.

Ancestor-Pfade

Entitäten in Cloud Datastore sind hierarchisch organisiert, ähnlich der Verzeichnisstruktur eines Dateisystems. Wenn Sie eine Entität erstellen, können Sie optional eine weitere Entität als übergeordnetes Element angeben. Die neue Entität ist dann ein untergeordnetes Element der übergeordneten Entität. Im Gegensatz zu einem Dateisystem muss die übergeordnete Entität nicht tatsächlich vorhanden sein. Eine Entität ohne übergeordnetes Element wird als Stammentität bezeichnet. Die Verknüpfung zwischen einer Entität und ihrer übergeordneten Entität ist dauerhaft und kann nicht geändert werden, nachdem die Entität erstellt wurde. Cloud Datastore weist zwei Entitäten mit derselben übergeordneten Entität oder zwei Stammentitäten (Entitäten ohne übergeordnete Entität) niemals dieselbe numerische ID zu.

Alle übergeordneten Elemente einer Entität werden als ihre Ancestors bezeichnet und alle untergeordneten Entitäten sind ihre Nachfolger. Eine Stammentität und alle ihre Nachfolger gehören zu derselben Entitätengruppe. Die Abfolge der Entitäten, von einer Stammentität über die untergeordneten Elemente bis zu einer bestimmten Entität, bildet den Ancestor-Pfad. Der vollständige Schlüssel, der die Entität identifiziert, besteht aus einer Abfolge von Art/Kennungs-Paaren, die den Ancestor-Pfad angeben und mit dem Paar der Entität selbst enden:

[Person:GreatGrandpa, Person:Grandpa, Person:Dad, Person:Me]

Bei einer Stammentität ist der Ancestor-Pfad leer und der Schlüssel besteht ausschließlich aus der eigenen Art und der eigenen Kennung der Entität:

[Person:GreatGrandpa]

Dieses Konzept wird anhand des folgenden Diagramms veranschaulicht:

Zeigt die Beziehung der Stammentität zu den untergeordneten Entitäten in der Entitätengruppe an

Wenn Sie das übergeordnete Element einer Entität festlegen möchten, geben Sie den Schlüssel der übergeordneten Entität beim Erstellen der untergeordneten Entität als Argument für den Konstruktor Entity() an. Sie können den Schlüssel abrufen, indem Sie die Methode getKey() der übergeordneten Entität aufrufen:

Entity employee = new Entity("Employee");
datastore.put(employee);

Entity address = new Entity("Address", employee.getKey());
datastore.put(address);

Hat die neue Entität auch einen Schlüsselnamen, übergeben Sie dem Entity()-Konstruktor beim Erstellen der Entität den Namen als zweites Argument und den Schlüssel der übergeordneten Entität als drittes Argument:

Entity address = new Entity("Address", "addr1", employee.getKey());

Transaktionen und Entitätengruppen

Jeder Vorgang zum Erstellen, Aktualisieren und Löschen einer Entität findet im Rahmen einer Transaktion statt. Eine einzelne Transaktion kann eine beliebige Anzahl solcher Vorgänge umfassen. Um die Konsistenz der Daten zu wahren, sorgt die Transaktion dafür, dass entweder alle enthaltenen Vorgänge auf Datastore als Einheit angewendet werden oder überhaupt nicht, sofern einer der Vorgänge fehlgeschlagen ist. Darüber hinaus greifen alle strikt konsistenten Lesevorgänge (Ancestor-Abfragen oder -Abrufe) innerhalb derselben Transaktion auf einen konsistenten Snapshot der Daten zurück.

Wie oben bereits erwähnt besteht eine Entitätengruppe aus einer Reihe von Entitäten, die über einen Ancestor-Pfad mit einem gemeinsamen Stammelement verbunden sind. Die Anordnung von Daten in Entitätengruppen kann einschränken, welche Transaktionen ausgeführt werden können:

  • Alle Daten, auf die eine Transaktion zugreift, müssen in maximal 25 Entitätengruppen enthalten sein.
  • Wenn Sie Abfragen innerhalb einer Transaktion verwenden möchten, müssen die Daten so in Entitätengruppen angeordnet werden, dass Sie Ancestor-Filter angeben können, die mit den richtigen Daten übereinstimmen.
  • Es gibt einen Schreibdurchsatzgrenzwert von ca. einer Transaktion pro Sekunde innerhalb einer einzelnen Entitätengruppe. Diese Begrenzung ist vorhanden, weil Datastore eine synchrone Replikation ohne Master jeder Entitätengruppe über einen breiten geografischen Bereich hinweg durchführt, um hohe Verlässlichkeit und Fehlertoleranz zu ermöglichen.

In vielen Anwendungen kann es akzeptabel sein, für den Abruf einer breiten Ansicht nicht zusammengehöriger Daten Eventual Consistency zu verwenden, also eine entitätengruppenübergreifende Nicht-Ancestor-Abfrage, die gelegentlich etwas veraltete Daten zurückgeben kann. Anschließend wird dann strikte Konsistenz (eine Ancestor-Abfrage oder ein get einer einzelnen Entität) verwendet, um eine einzelne Gruppe von eng zusammengehörigen Daten anzusehen oder zu bearbeiten. In derartigen Anwendungen ist die Gruppierung von eng zusammengehörigen Daten in Entitätsgruppen im Allgemeinen ein guter Ansatz. Weitere Informationen finden Sie unter Für strikte Konsistenz strukturieren.

Attribute und Werttypen

Die mit einer Entität verknüpften Datenwerte bestehen aus einem oder mehreren Attributen. Jedes Attribut hat einen Namen und einen oder mehrere Werte. Ein Attribut kann Werte mit mehr als einem Typ haben und zwei Entitäten können Werte unterschiedlichen Typs für dasselbe Attribut haben. Attribute können indexiert oder nicht indexiert sein. Abfragen, die nach einem Attribut A sortieren oder filtern, ignorieren Entitäten, bei denen A nicht indexiert ist. Eine Entität kann höchstens 20.000 indexierte Attribute haben.

Die folgenden Werttypen werden unterstützt:

Werttyp Java-Typ(en) Sortierreihenfolge Hinweise
Ganzzahl short
int
long
java.lang.Short
java.lang.Integer
java.lang.Long
Numerisch Gespeichert als lange Ganzzahl, dann Umwandlung in den Feldtyp

Überlauf der außerhalb des Bereichs liegenden Werte
Gleitkommazahl float
double
java.lang.Float
java.lang.Double
Numerisch 64 Bit mit doppelter Genauigkeit,
IEEE 754
Boolesch boolean
java.lang.Boolean
false<true
Textstring (kurz) java.lang.String Unicode Bis zu 1.500 Byte

Werte über 1.500 Byte geben IllegalArgumentException aus
Textstring (lang) com.google.appengine.api.datastore.Text Bis zu 1 Megabyte

Nicht indexiert
Bytestring (kurz) com.google.appengine.api.datastore.ShortBlob Bytereihenfolge Bis zu 1.500 Byte

Werte, die länger als 1.500 Byte sind, geben IllegalArgumentException aus
Bytestring (lang) com.google.appengine.api.datastore.Blob Bis zu 1 Megabyte

Nicht indexiert
Datum und Uhrzeit java.util.Date Chronologisch
Geografischer Punkt com.google.appengine.api.datastore.GeoPt Nach Breitengrad,
dann nach Längengrad
Postanschrift com.google.appengine.api.datastore.PostalAddress Unicode
Telefonnummer com.google.appengine.api.datastore.PhoneNumber Unicode
E-Mail-Adresse com.google.appengine.api.datastore.Email Unicode
Nutzer eines Google-Kontos com.google.appengine.api.users.User E-Mail-Adresse
in Unicode-Reihenfolge
Instant-Messaging-Handle com.google.appengine.api.datastore.IMHandle Unicode
Link com.google.appengine.api.datastore.Link Unicode
Kategorie com.google.appengine.api.datastore.Category Unicode
Bewertung com.google.appengine.api.datastore.Rating Numerisch
Datastore-Schlüssel com.google.appengine.api.datastore.Key
oder das referenzierte Objekt (als untergeordnetes Element)
Nach Pfadelementen
(Art, Kennung,
Art, Kennung...)
Bis zu 1.500 Byte

Werte, die länger als 1.500 Byte sind, geben IllegalArgumentException aus
Blobstore-Schlüssel com.google.appengine.api.blobstore.BlobKey Bytereihenfolge
Eingebettete Entität com.google.appengine.api.datastore.EmbeddedEntity Nicht indexiert
Null null

Wichtig: Das Speichern von users.User als Attributwert sollte unbedingt vermieden werden, da die E-Mail-Adresse und die eindeutige ID enthalten sind. Wenn ein Nutzer seine E-Mail-Adresse ändert und Sie das alte gespeicherte Objekt user.User mit dem neuen user.User-Wert vergleichen, würden sie nicht übereinstimmen. Stattdessen sollten Sie den Nutzer-ID-Wert User als stabile eindeutige Kennung des Nutzers verwenden.

Für Textstrings und nicht codierte Binärdaten (Bytestrings) unterstützt Datastore zwei Werttypen:

  • Kurze Strings (bis zu 1.500 Byte) werden indexiert und können in Filterbedingungen der Abfrage und in Sortierfolgen verwendet werden.
  • Lange Strings (bis zu 1 Megabyte) werden nicht indexiert und können nicht in Abfragefiltern und Sortierfolgen verwendet werden.
Hinweis: Der lange Bytestringtyp lautet in der Datastore API Blob. Dieser Typ steht nicht im Zusammenhang mit den Blobs in der Blobstore API.

Wenn eine Abfrage ein Attribut mit Werten verschiedener Typen enthält, verwendet Datastore eine deterministische Sortierung anhand der internen Darstellungen:

  1. Nullwerte
  2. Festkommazahlen
    • Ganzzahlen
    • Datums- und Uhrzeitwerte
    • Bewertungen
  3. Boolesche Werte
  4. Bytesequenzen
    • Bytestring
    • Unicode-String
    • Blobstore-Schlüssel
  5. Gleitkommazahlen
  6. Geografische Punkte
  7. Nutzer von Google-Konten
  8. Datastore-Schlüssel

Da lange Textstrings, lange Bytestrings und eingebettete Entitäten nicht indexiert werden, ist für sie keine Reihenfolge definiert.

Mit Entitäten arbeiten

Anwendungen können mit der Datastore API Entitäten erstellen, abrufen, aktualisieren und löschen. Wenn die Anwendung den vollständigen Schlüssel für eine Entität kennt (oder ihn aus dem übergeordneten Schlüssel, der Art und der Kennung ableiten kann), kann sie mit dem Schlüssel direkt mit der Entität arbeiten. Eine Anwendung kann den Schlüssel einer Entität auch als Ergebnis einer Datastore-Abfrage abrufen. Weitere Informationen finden Sie unter Datastore-Abfragen.

Die Java Datastore API verwendet zur Verarbeitung von Entitäten Methoden der Schnittstelle DatastoreService. Sie erhalten ein DatastoreService-Objekt, indem Sie die statische Methode DatastoreServiceFactory.getDatastoreService() aufrufen:

DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();

Entität erstellen

Sie können eine neue Entität erstellen, indem Sie eine Instanz der Klasse Entity erstellen, die die Art der Entität als Argument für den Konstruktor Entity() liefert.

Nachdem Sie gegebenenfalls Attribute für die Entität eingegeben haben, speichern Sie sie im Datenspeicher. Dazu übergeben Sie die Entität als Argument an die Methode DatastoreService.put(). Sie können den Schlüsselnamen der Entität angeben, wenn Sie ihn als zweites Argument an den Konstruktor übergeben:

Entity employee = new Entity("Employee", "asalieri");
// Set the entity properties.
// ...
datastore.put(employee);

Wenn Sie keinen Schlüsselnamen angeben, generiert Datastore automatisch eine numerische ID für den Schlüssel der Entität:

Entity employee = new Entity("Employee");
// Set the entity properties.
// ...
datastore.put(employee);

Entität abrufen

Um eine Entität mit einem bestimmten Schlüssel abzurufen, übergeben Sie das Objekt Key an die Methode DatastoreService.get():

// Key employeeKey = ...;
Entity employee = datastore.get(employeeKey);

Entität aktualisieren

Wenn Sie eine vorhandene Entität aktualisieren möchten, ändern Sie die Attribute des Entitätsobjekts und übergeben es dann an die Methode DatastoreService.put(). Die bestehende Entität wird mit den Objektdaten überschrieben. Bei jedem Aufruf von put() wird das ganze Objekt an Datastore gesendet.

Entität löschen

Sie können eine Entität unter Angabe ihres Schlüssels mit der Methode DatastoreService.delete() löschen:

// Key employeeKey = ...;
datastore.delete(employeeKey);

Wiederkehrende Attribute

Sie können mehrere Werte in einem einzelnen Attribut speichern.

Entity employee = new Entity("Employee");
ArrayList<String> favoriteFruit = new ArrayList<String>();
favoriteFruit.add("Pear");
favoriteFruit.add("Apple");
employee.setProperty("favoriteFruit", favoriteFruit);
datastore.put(employee);

// Sometime later
employee = datastore.get(employee.getKey());
@SuppressWarnings("unchecked") // Cast can't verify generic type.
    ArrayList<String> retrievedFruits = (ArrayList<String>) employee
    .getProperty("favoriteFruit");

Eingebettete Entitäten

In manchen Fällen ist es sinnvoll, eine Entität als Attribut in eine andere Entität einzubetten. Dies kann beispielsweise nützlich sein, um eine hierarchische Struktur von Attributwerten innerhalb einer Entität zu erstellen. Mit der Java-Klasse EmbeddedEntity ist das kein Problem:

// Entity employee = ...;
EmbeddedEntity embeddedContactInfo = new EmbeddedEntity();

embeddedContactInfo.setProperty("homeAddress", "123 Fake St, Made, UP 45678");
embeddedContactInfo.setProperty("phoneNumber", "555-555-5555");
embeddedContactInfo.setProperty("emailAddress", "test@example.com");

employee.setProperty("contactInfo", embeddedContactInfo);

Ist eine eingebettete Entität in Indexen enthalten, können Sie untergeordnete Attribute abfragen. Schließen Sie eine eingebettete Entität von der Indexierung aus, werden auch alle untergeordneten Attribute von der Indexierung ausgeschlossen. Sie können einer eingebetteten Entität optional einen Schlüssel zuordnen. Aber im Gegensatz zu einer vollwertigen Entität ist der Schlüssel nicht erforderlich und kann, selbst wenn er vorhanden ist, nicht zum Abrufen der Entität verwendet werden.

Statt die Attribute der eingebetteten Entität manuell auszufüllen, können Sie sie mit der Methode setPropertiesFrom() aus einer vorhandenen Entität kopieren:

// Entity employee = ...;
// Entity contactInfo = ...;
EmbeddedEntity embeddedContactInfo = new EmbeddedEntity();

embeddedContactInfo.setKey(contactInfo.getKey()); // Optional, used so we can recover original.
embeddedContactInfo.setPropertiesFrom(contactInfo);

employee.setProperty("contactInfo", embeddedContactInfo);

Sie können später dieselbe Methode zum Wiederherstellen der ursprünglichen Entität aus der eingebetteten Entität verwenden:

Entity employee = datastore.get(employeeKey);
EmbeddedEntity embeddedContactInfo = (EmbeddedEntity) employee.getProperty("contactInfo");

Key infoKey = embeddedContactInfo.getKey();
Entity contactInfo = new Entity(infoKey);
contactInfo.setPropertiesFrom(embeddedContactInfo);

Batchvorgänge

Die DatastoreService-Methoden put(), get() und delete() und ihre Gegenstücke in AsyncDatastoreService haben Batchversionen, die ein iterierbares-Objekt der Klasse Entity für put(), Key für get() und delete() akzeptieren. Dadurch können mehrere Entitäten mit einem einzigen Cloud Datastore-Aufruf verarbeitet werden:

Entity employee1 = new Entity("Employee");
Entity employee2 = new Entity("Employee");
Entity employee3 = new Entity("Employee");
// ...

List<Entity> employees = Arrays.asList(employee1, employee2, employee3);
datastore.put(employees);

Diese Batchvorgänge gruppieren alle Entitäten oder Schlüssel nach Entitätengruppe und führen dann den angeforderten Vorgang für alle Entitätengruppen parallel durch. Solche Batchaufrufe sind schneller als separate Aufrufe für jede einzelne Entität, weil nur der Overhead für einen einzigen Dienstaufruf anfällt. Wenn mehrere Entitätengruppen betroffen sind, wird die Arbeit für alle Gruppen im Parallelverfahren auf der Serverseite ausgeführt.

Schlüssel generieren

Anwendungen können die Klasse KeyFactory verwenden, um ein Key -Objekt für eine Entität aus bekannten Komponenten wie Typ und ID der Entität zu erstellen. Für eine Entität ohne übergeordnetes Element übergeben Sie den Typ und die ID an die statische Methode KeyFactory.createKey(), um den Schlüssel zu erstellen. In den folgenden Beispielen wird ein Schlüssel für eine Entität vom Typ Person mit dem Schlüsselnamen "GreatGrandpa" oder der numerischen ID 74219 erstellt:

Key k1 = KeyFactory.createKey("Person", "GreatGrandpa");
Key k2 = KeyFactory.createKey("Person", 74219);

Wenn der Schlüssel eine Pfadkomponente enthält, können Sie den Pfad mit der Hilfsklasse KeyFactory.Builder erstellen. Die Methode addChild dieser Klasse fügt dem Pfad eine einzelne Entität hinzu und gibt den Builder selbst zurück, sodass Sie eine Reihe von Aufrufen, beginnend mit der Stammentität, verketten können, um den Pfad eine Entität aufzubauen nacheinander. Rufen Sie nach dem Erstellen des vollständigen Pfads getKey auf, um den resultierenden Schlüssel abzurufen:

Key k =
    new KeyFactory.Builder("Person", "GreatGrandpa")
        .addChild("Person", "Grandpa")
        .addChild("Person", "Dad")
        .addChild("Person", "Me")
        .getKey();

Die Klasse KeyFactory enthält außerdem die statischen Methoden keyToString und stringToKey für die Konvertierung zwischen Schlüsseln und ihren Stringdarstellungen:

String personKeyStr = KeyFactory.keyToString(k);

// Some time later (for example, after using personKeyStr in a link).
Key personKey = KeyFactory.stringToKey(personKeyStr);
Entity person = datastore.get(personKey);

Die Stringdarstellung eines Schlüssels ist "websicher". Das bedeutet, dass sie keine Zeichen enthält, die in HTML oder URLs als Sonderzeichen gelten.

Leere Liste verwenden

In der Vergangenheit konnte Datastore keine Attribute für eine leere Liste darstellen. Im Java SDK wurden leere Sammlungen daher als Nullwerte gespeichert, wodurch es nicht möglich ist, zwischen Nullwerten und leeren Listen zu unterscheiden. Zur Aufrechterhaltung der Abwärtskompatibilität bleibt dies das Standardverhalten, das sich so zusammenfassen lässt:

  • Nullattribute werden in Datastore als Null geschrieben.
  • Leere Sammlungen werden in den Datenspeicher als Null geschrieben.
  • Nullwerte werden von Datastore als Null gelesen.
  • Leere Sammlungen werden als Null gelesen.

Wenn Sie jedoch das Standardverhalten ändern, unterstützt das Java SDK das Speichern leerer Listen. Wir empfehlen, die Auswirkungen zu erwägen, die durch eine Änderung des Standardverhaltens Ihrer Anwendung entstehen, und anschließend die Unterstützung für leere Listen zu aktivieren.

Legen Sie das Attribut DATASTORE_EMPTY_LIST_SUPPORT während der Initialisierung der Anwendung fest, um das Standardverhalten so zu ändern, dass Sie leere Listen verwenden können:

System.setProperty(DatastoreServiceConfig.DATASTORE_EMPTY_LIST_SUPPORT, Boolean.TRUE.toString());

Wird dieses Attribut wie oben auf true gesetzt, gilt:

  • Nullattribute werden in Datastore als Null geschrieben.
  • Leere Sammlungen werden als leere Liste in Datastore geschrieben.
  • Nullwerte werden von Datastore als Null gelesen.
  • Beim Lesen aus Datastore wird eine leere Liste als leere Sammlung zurückgegeben.