1. Introduzione alle operazioni ent sugli enti
Questa guida fornisce una panoramica completa per padroneggiare le operazioni sugli enti nel framework ent
, coprendo l'intero processo di creazione, interrogazione, aggiornamento ed eliminazione degli enti. È adatta ai principianti per immergersi gradualmente nella funzionalità principale di ent
.
3. Operazione di Creazione dell'Entità
3.1 Creazione di un Singolo Ente
Creare un ente è l'operazione fondamentale per la persistenza dei dati. Di seguito sono riportati i passaggi per creare un singolo oggetto entità utilizzando il framework ent
e salvarlo nel database:
- In primo luogo, definire la struttura e i campi di un'entità, ovvero definire il modello dell'entità nel file
schema
. - Eseguire il comando
ent generate
per generare il codice operativo dell'ente corrispondente. - Utilizzare il metodo
Create
generato per creare un nuovo ente e impostare i valori dei campi dell'ente tramite chiamate concatenabili. - Infine, chiamare il metodo
Save
per salvare l'ente nel database.
Di seguito è riportato un esempio che mostra come creare e salvare un'entità utente:
package main
import (
"context"
"log"
"entdemo/ent"
)
func main() {
// Crea un'istanza Client per l'interazione con il database
client, err := ent.Open("sqlite3", "file:ent?mode=memory&cache=shared&_fk=1")
if err != nil {
log.Fatalf("Impossibile aprire la connessione al database: %v", err)
}
defer client.Close()
// Crea un contesto
ctx := context.Background()
// Crea un'entità utente utilizzando il Client
a8m, err := client.User.
Create().
SetName("a8m").
Save(ctx)
if err != nil {
log.Fatalf("Impossibile creare l'entità utente: %v", err)
}
// Entità salvata con successo nel database
log.Printf("Entità utente salvata: %v", a8m)
}
In questo esempio, viene prima creato un client di database client
. Successivamente, il metodo User.Create
viene utilizzato per impostare gli attributi del nuovo utente e, infine, viene chiamato il metodo Save
per salvare l'utente nel database.
3.2 Creazione Batch dell'Entità
In determinati scenari, potrebbe essere necessario creare più entità, ad esempio durante l'inizializzazione del database o le operazioni di importazione di dati in blocco. Il framework ent
fornisce la capacità di creare entità in batch, che offre prestazioni migliori rispetto alla creazione e al salvataggio individuale delle entità.
I passaggi per la creazione batch dell'entità sono i seguenti:
- Utilizzare il metodo
CreateBulk
invece del metodoCreate
, che consente la creazione di più entità in un'unica operazione. - Chiamare
Create
per ogni entità da creare. - Una volta create tutte le entità, utilizzare il metodo
Save
per salvare le entità nel database in blocco.
Di seguito è riportato un esempio di creazione batch dell'entità:
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("Impossibile aprire la connessione al database: %v", err)
}
defer client.Close()
ctx := context.Background()
// Crea in batch le entità Pet
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("Impossibile creare in batch le entità Pet: %v", err)
}
log.Printf("Create %d entità Pet in batch\n", len(pets))
}
In questo esempio, viene prima creato un client
, e successivamente vengono costruite più entità Pet
utilizzando il metodo CreateBulk
, impostando i loro nomi e i campi del proprietario. Tutte le entità vengono salvate nel database in una volta sola quando viene chiamato il metodo Save
, offrendo prestazioni migliori per gestire grandi quantità di dati.
4. Operazioni di Query dell'Entità
4.1 Query di base
Il querying del database è il modo fondamentale per recuperare informazioni. In ent
, il metodo Query
viene utilizzato per avviare una query. Di seguito sono riportati i passaggi e un esempio di query di entità di base:
- Assicurati di avere un'istanza utilizzabile di
Client
. - Usa
Client.Query()
o metodi helper dell'entità comePet.Query()
per creare una query. - Aggiungi le condizioni di filtraggio secondo necessità, come ad esempio
Where
. - Esegui la query e recupera i risultati chiamando il metodo
All
.
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("Impossibile aprire la connessione al database: %v", err)
}
defer client.Close()
ctx := context.Background()
// Query di tutti gli utenti con nome "a8m"
users, err := client.User.
Query().
Where(user.NameEQ("a8m")).
All(ctx)
if err != nil {
log.Fatalf("Impossibile interrogare gli utenti: %v", err)
}
for _, u := range users {
log.Printf("Utente trovato: %#v\n", u)
}
}
Questo esempio dimostra come trovare tutti gli utenti con il nome "a8m".
4.2 Paginazione e ordinamento
La paginazione e l'ordinamento sono funzionalità avanzate comunemente utilizzate durante il querying, utilizzate per controllare l'ordine di output e la quantità di dati. Ecco come ottenere query di paginazione e ordinamento utilizzando ent
:
- Utilizza il metodo
Limit
per impostare il numero massimo di risultati da restituire. - Utilizza il metodo
Offset
per saltare alcuni dei risultati precedenti. - Utilizza il metodo
Order
per specificare il campo di ordinamento e la direzione.
Ecco un esempio di query di paginazione e ordinamento:
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("Impossibile aprire la connessione al database: %v", err)
}
defer client.Close()
ctx := context.Background()
// Query di Pets in ordine decrescente di età con paginazione
pets, err := client.Pet.
Query().
Order(ent.Desc(pet.FieldAge)).
Limit(10).
Offset(0).
All(ctx)
if err != nil {
log.Fatalf("Impossibile interrogare i Pets: %v", err)
}
for _, p := range pets {
log.Printf("Animale domestico trovato: %#v\n", p)
}
}
Questo esempio dimostra come recuperare la prima pagina, fino a 10 record, di animali domestici ordinati in ordine decrescente per età. Modificando i valori di Limit
e Offset
, è possibile ottenere la paginazione dell'intero set di dati.
5. Operazioni di aggiornamento dell'entità
5.1 Aggiornamento di un'entità singola
In molte applicazioni, l'aggiornamento delle entità è una parte essenziale delle operazioni quotidiane. In questa sezione, dimostreremo come utilizzare il framework Ent per aggiornare una singola entità nel database.
In primo luogo, supponendo che sia necessario aggiornare l'età di un utente, è possibile utilizzare il metodo Update
generato da Ent.
// Supponendo che abbiamo già un'entità utente 'a8m' e un contesto 'ctx'
a8m, err := a8m.Update(). // Crea un costruttore di aggiornamento utente
SetAge(30). // Imposta l'età dell'utente a 30 anni
Save(ctx) // Esegui l'operazione di salvataggio e restituisci il risultato
if err != nil {
log.Fatalf("Impossibile aggiornare l'utente: %v", err)
}
È anche possibile aggiornare contemporaneamente più campi:
a8m, err := a8m.Update().
SetAge(30). // Aggiorna l'età
SetName("Ariel"). // Aggiorna il nome
AddRank(10). // Aumenta il rango di 10
Save(ctx)
if err != nil {
log.Fatalf("Impossibile aggiornare l'utente: %v", err)
}
L'operazione di aggiornamento può essere concatenata, il che è molto flessibile e facile da leggere. Chiamare il metodo Save
eseguirà l'aggiornamento e restituirà l'entità aggiornata o un messaggio di errore.
5.2 Aggiornamenti Condizionali
Ent ti consente di effettuare aggiornamenti basati su condizioni. Ecco un esempio in cui verranno aggiornati solo gli utenti che soddisfano condizioni specifiche.
// Presumendo di avere l'`id` di un utente e di voler contrassegnare quell'utente come completato per la versione `currentVersion`
err := client.Todo.
UpdateOneID(id). // Crea un builder per aggiornare tramite l'ID dell'utente
SetStatus(todo.StatusDone).
AddVersion(1).
Where(
todo.Version(currentVersion), // L'operazione di aggiornamento viene eseguita solo quando la versione corrente corrisponde
).
Exec(ctx)
switch {
case ent.IsNotFound(err):
fmt.Println("Attività non trovata")
case err != nil:
fmt.Println("Errore di aggiornamento:", err)
}
Quando si utilizzano gli aggiornamenti condizionali, il metodo .Where()
deve essere coinvolto. Questo ti consente di determinare se l'aggiornamento deve essere eseguito in base ai valori attuali nel database, il che è cruciale per garantire la coerenza e l'integrità dei dati.
6. Operazioni di Eliminazione dell'Entità
6.1 Eliminazione di una Singola Entità
L'eliminazione delle entità è un'altra funzione importante nelle operazioni del database. Il framework Ent fornisce un'API semplice per eseguire operazioni di eliminazione.
Nell'esempio seguente viene mostrato come eliminare un'entità utente specificata:
err := client.User.
DeleteOne(a8m). // Crea un builder di eliminazione utente
Exec(ctx) // Esegue l'operazione di eliminazione
if err != nil {
log.Fatalf("Impossibile eliminare l'utente: %v", err)
}
6.2 Eliminazione Condizionale
Analogamente alle operazioni di aggiornamento, possiamo anche eseguire operazioni di eliminazione in base a condizioni specifiche. In certi scenari, potremmo voler eliminare solo le entità che soddisfano condizioni specifiche. Utilizzando il metodo .Where()
è possibile definire tali condizioni:
// Supponiamo di voler eliminare tutti i file con un tempo di aggiornamento precedente a una certa data
affected, err := client.File.
Delete().
Where(file.UpdatedAtLT(date)). // Esegui l'eliminazione solo se il tempo di aggiornamento del file è precedente alla data specificata
Exec(ctx)
if err != nil {
log.Fatalf("Impossibile eliminare i file: %v", err)
}
// Questa operazione restituisce il numero di record interessati dall'operazione di eliminazione
fmt.Printf("%d file sono stati eliminati\n", affected)
L'utilizzo di operazioni di eliminazione condizionali garantisce un controllo preciso sulle operazioni dei dati, garantendo che vengano eliminati solo le entità che soddisfano effettivamente le condizioni. Ciò migliora la sicurezza e la affidabilità delle operazioni del database.