1. Einführung in die Entity-Operationen von ent
In diesem Tutorial werden Sie umfassend durch die Beherrschung der Entity-Operationen im ent
-Framework geführt, die den vollständigen Prozess der Erstellung, Abfrage, Aktualisierung und Löschung von Entitäten abdecken. Es eignet sich für Anfänger, um sich allmählich in die Kernfunktionalität von ent
einzuarbeiten.
3. Entity-Erstellungsoperation
3.1 Erstellung einer einzelnen Entität
Die Erstellung einer Entität ist die grundlegende Operation zur Datenpersistenz. Im Folgenden finden Sie die Schritte zur Erstellung eines einzelnen Entitätsobjekts mithilfe des ent
-Frameworks und zur Speicherung in der Datenbank:
- Definieren Sie zunächst die Struktur und Felder einer Entität, d. h. definieren Sie das Modell der Entität in der
schema
-Datei. - Führen Sie den Befehl
ent generate
aus, um den entsprechenden Entitätsoperationscode zu generieren. - Verwenden Sie die generierte
Create
-Methode, um eine neue Entität zu erstellen, und setzen Sie die Feldwerte der Entität durch verkettete Aufrufe. - Rufen Sie schließlich die
Save
-Methode auf, um die Entität in der Datenbank zu speichern.
Im Folgenden finden Sie ein Beispiel, das zeigt, wie eine Benutzerentität erstellt und gespeichert wird:
package main
import (
"context"
"log"
"entdemo/ent"
)
func main() {
// Erstellen einer Client-Instanz für die Datenbankinteraktion
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
if err != nil {
log.Fatalf("Fehler beim Öffnen der Datenbankverbindung: %v", err)
}
defer client.Close()
// Erstellen eines Kontexts
ctx := context.Background()
// Erstellen einer Benutzerentität mithilfe des Clients
a8m, err := client.User.
Create().
SetName("a8m").
Save(ctx)
if err != nil {
log.Fatalf("Fehler beim Erstellen der Benutzerentität: %v", err)
}
// Entität erfolgreich in der Datenbank gespeichert
log.Printf("Benutzerentität gespeichert: %v", a8m)
}
In diesem Beispiel wird zunächst ein Datenbankclient client
erstellt. Anschließend wird die Methode User.Create
verwendet, um die Attribute des neuen Benutzers festzulegen, und schließlich wird die Methode Save
aufgerufen, um den Benutzer in der Datenbank zu speichern.
3.2 Batch-Entitätserstellung
In bestimmten Szenarien kann es erforderlich sein, mehrere Entitäten zu erstellen, z. B. während der Datenbankinitialisierung oder bei Massendatenimportoperationen. Das ent
-Framework ermöglicht die Erstellung von Entitäten im Batch, was im Vergleich zur individuellen Erstellung und Speicherung von Entitäten eine bessere Leistung bietet.
Die Schritte zur Batch-Entitätserstellung lauten wie folgt:
- Verwenden Sie die Methode
CreateBulk
anstelle der MethodeCreate
, die die Erstellung mehrerer Entitäten in einer einzigen Operation ermöglicht. - Rufen Sie für jede zu erstellende Entität
Create
auf. - Sobald alle Entitäten erstellt wurden, verwenden Sie die Methode
Save
, um die Entitäten in der Datenbank im Batch zu speichern.
Im Folgenden finden Sie ein Beispiel zur Batch-Entitätserstellung:
package main
import (
"context"
"log"
"entdemo/ent"
)
func main() {
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
if err != nil {
log.Fatalf("Fehler beim Öffnen der Datenbankverbindung: %v", err)
}
defer client.Close()
ctx := context.Background()
// Batch-Erstellung von Pet-Entitäten
pets, err := client.Pet.CreateBulk(
client.Pet.Create().SetName("pedro").SetOwner(a8m),
client.Pet.Create().SetName("xabi").SetOwner(a8m),
client.Pet.Create().SetName("layla").SetOwner(a8m),
).Save(ctx)
if err != nil {
log.Fatalf("Fehler beim Batch-Erstellen von Pet-Entitäten: %v", err)
}
log.Printf("In Batch %d Pet-Entitäten erstellt\n", len(pets))
}
In diesem Beispiel wird zuerst ein client
erstellt, und dann werden mehrere Pet
-Entitäten mithilfe der Methode CreateBulk
erstellt, wobei ihre Namen und Besitzerfelder festgelegt werden. Alle Entitäten werden gleichzeitig in der Datenbank gespeichert, wenn die Methode Save
aufgerufen wird, was eine bessere Leistung für die Verarbeitung großer Datenmengen bietet.
4. Entitätsabfrageoperationen
4.1 Grundlegende Abfrage
Datenbankabfragen sind der grundlegende Weg, um Informationen abzurufen. In ent
wird die Methode Query
verwendet, um eine Abfrage zu starten. Nachfolgend sind die Schritte und ein Beispiel für grundlegende Entity-Abfragen aufgeführt:
- Stellen Sie sicher, dass Sie eine verwendbare
Client
-Instanz haben. - Verwenden Sie
Client.Query()
oder Entity-Hilfsmethoden wiePet.Query()
, um eine Abfrage zu erstellen. - Fügen Sie bei Bedarf Filterbedingungen hinzu, wie z. B.
Where
. - Führen Sie die Abfrage aus und rufen Sie die Ergebnisse durch Aufruf der Methode
All
ab.
package main
import (
"context"
"log"
"entdemo/ent"
"entdemo/ent/user"
)
func main() {
client, err := ent.Open("sqlite3", "file:ent?cache=shared&_fk=1")
if err != nil {
log.Fatalf("Fehler beim Öffnen der Datenbankverbindung: %v", err)
}
defer client.Close()
ctx := context.Background()
// Abfrage aller Benutzer mit dem Namen "a8m"
users, err := client.User.
Query().
Where(user.NameEQ("a8m")).
All(ctx)
if err != nil {
log.Fatalf("Fehler beim Abfragen von Benutzern: %v", err)
}
for _, u := range users {
log.Printf("Benutzer gefunden: %#v\n", u)
}
}
Dieses Beispiel zeigt, wie alle Benutzer mit dem Namen "a8m" gefunden werden.
4.2 Seitenumbruch und Sortierung
Seitenumbruch und Sortierung sind häufig verwendete erweiterte Funktionen bei Abfragen, um die Ausgabereihenfolge und -menge von Daten zu steuern. So funktioniert die Umsetzung von Seitenumbruch- und Sortierabfragen mit ent
:
- Verwenden Sie die Methode
Limit
, um die maximale Anzahl der zurückzugebenden Ergebnisse festzulegen. - Verwenden Sie die Methode
Offset
, um einige der vorherigen Ergebnisse zu überspringen. - Verwenden Sie die Methode
Order
, um das Sortierfeld und die Richtung anzugeben.
Hier ist ein Beispiel für eine Seitenumbruch- und Sortierabfrage:
package main
import (
"context"
"log"
"entdemo/ent"
"entdemo/ent/pet"
)
func main() {
client, err := ent.Open("sqlite3", "file:ent?cache=shared&_fk=1")
if err != nil {
log.Fatalf("Fehler beim Öffnen der Datenbankverbindung: %v", err)
}
defer client.Close()
ctx := context.Background()
// Abfrage von Haustieren in absteigender Reihenfolge nach Alter mit Seitenumbruch
pets, err := client.Pet.
Query().
Order(ent.Desc(pet.FieldAge)).
Limit(10).
Offset(0).
All(ctx)
if err != nil {
log.Fatalf("Fehler beim Abfragen von Haustieren: %v", err)
}
for _, p := range pets {
log.Printf("Haustier gefunden: %#v\n", p)
}
}
Dieses Beispiel zeigt, wie die erste Seite mit bis zu 10 Datensätzen von Haustieren in absteigender Reihenfolge nach Alter abgerufen wird. Durch Ändern der Werte von Limit
und Offset
können Sie das gesamte Datensatz durchblättern.
5. Entity-Aktualisierungsvorgänge
5.1 Aktualisieren einer einzelnen Entity
In vielen Anwendungen ist die Aktualisierung von Entities ein wesentlicher Bestandteil des täglichen Betriebs. In diesem Abschnitt wird gezeigt, wie das Ent-Framework verwendet wird, um eine einzelne Entity in der Datenbank zu aktualisieren.
Angenommen, wir müssen das Alter eines Benutzers aktualisieren, können wir die von Ent generierte Update
-Methode nutzen.
// Angenommen, wir haben bereits eine Benutzer-Entity 'a8m' und einen Kontext 'ctx'
a8m, err := a8m.Update(). // Erstellen eines Benutzer-Aktualisierungs-Builder
SetAge(30). // Setzen des Alters des Benutzers auf 30 Jahre
Save(ctx) // Durchführen der Speicheroperation und Rückgabe des Ergebnisses
if err != nil {
log.Fatalf("Fehler beim Aktualisieren des Benutzers: %v", err)
}
Sie können auch mehrere Felder gleichzeitig aktualisieren:
a8m, err := a8m.Update().
SetAge(30). // Alter aktualisieren
SetName("Ariel"). // Name aktualisieren
AddRank(10). // Rang um 10 erhöhen
Save(ctx)
if err != nil {
log.Fatalf("Fehler beim Aktualisieren des Benutzers: %v", err)
}
Die Aktualisierung kann verkettet werden, was sehr flexibel und leicht lesbar ist. Durch Aufruf der Methode Save
wird die Aktualisierung durchgeführt und die aktualisierte Entity oder eine Fehlermeldung zurückgegeben.
5.2 Bedingte Aktualisierungen
Ent ermöglicht es Ihnen, Aktualisierungen basierend auf Bedingungen durchzuführen. Hier ist ein Beispiel, bei dem nur Benutzer, die bestimmte Bedingungen erfüllen, aktualisiert werden.
// Angenommen, wir haben die `id` eines Benutzers und wir möchten diesen Benutzer als erledigt für die Version `currentVersion` markieren
err := client.Todo.
UpdateOneID(id). // Erstellen eines Builders zur Aktualisierung anhand der Benutzer-ID
SetStatus(todo.StatusDone).
AddVersion(1).
Where(
todo.Version(currentVersion), // Die Aktualisierung wird nur ausgeführt, wenn die aktuelle Version übereinstimmt
).
Exec(ctx)
switch {
case ent.IsNotFound(err):
fmt.Println("Aufgabe nicht gefunden")
case err != nil:
fmt.Println("Fehler bei der Aktualisierung:", err)
}
Bei der Verwendung von bedingten Aktualisierungen muss die Methode .Where()
involviert sein. Dies ermöglicht es Ihnen zu bestimmen, ob die Aktualisierung basierend auf den aktuellen Werten in der Datenbank durchgeführt werden soll, was entscheidend für die Gewährleistung der Datenkonsistenz und -integrität ist.
6. Entitätslöschoperationen
6.1 Löschen einer Einzelnen Entität
Das Löschen von Entitäten ist eine weitere wichtige Funktion bei Datenbankoperationen. Das Ent-Framework bietet eine einfache API für Löschvorgänge.
Das folgende Beispiel zeigt, wie man eine bestimmte Benutzerentität löscht:
err := client.User.
DeleteOne(a8m). // Erstellen eines Benutzerlösch-Builders
Exec(ctx) // Führen Sie die Löschoperation aus
if err != nil {
log.Fatalf("Fehler beim Löschen des Benutzers: %v", err)
}
6.2 Bedingtes Löschen
Ähnlich wie bei Aktualisierungsvorgängen können auch Löschvorgänge basierend auf spezifischen Bedingungen durchgeführt werden. In bestimmten Szenarien möchten wir möglicherweise nur Entitäten löschen, die bestimmte Bedingungen erfüllen. Mit der Methode .Where()
können diese Bedingungen definiert werden:
// Angenommen, wir möchten alle Dateien löschen, die vor einem bestimmten Datum aktualisiert wurden
betroffen, err := client.File.
Delete().
Where(file.UpdatedAtLT(date)). //führen Sie die Löschung nur aus, wenn die Aktualisierungszeit der Datei früher als das angegebene Datum ist
Exec(ctx)
if err != nil {
log.Fatalf("Fehler beim Löschen der Dateien: %v", err)
}
// Diese Operation gibt die Anzahl der durch den Löschvorgang betroffenen Datensätze zurück
fmt.Printf("%d Dateien wurden gelöscht\n", betroffen)
Durch die Verwendung von bedingten Löschvorgängen wird eine präzise Kontrolle über unsere Datenoperationen sichergestellt, wodurch nur Entitäten gelöscht werden, die tatsächlich die Bedingungen erfüllen. Dies verbessert die Sicherheit und Zuverlässigkeit der Datenbankoperationen.