Nell’articolo di oggi vedremo come integrare un database oracle e come effettuare le operazione di lettua e scrittura.
Prima di tutto introduciamo il package per la gestione del db database/sql e insieme al package dobbiamo importare il driver specifico per il database cui connettersi. L’elenco dei driver disponibili e le relative basi di dati supportati sono disponibili al link https://github.com/golang/go/wiki/SQLDrivers. Per lavoro uso Oracle, pertanto nell’esempio integro il driver godror. Per poter usare questo driver occorre installarlo e configurarlo nell’ambiente go tramite la direttiva:
|
go get github.com/godror/godror |
Il driver è realizzato in cgo pertanto è richiesta la presenza di un gcc compiler, nel mio caso ho utilizzato quello disponibile all’indirizzo https://jmeubank.github.io/tdm-gcc/. Maggiori informazioni su godror sono disponibili al l’url https://github.com/godror/godror
Dopo aver installato gcc e godror possiamo finalmente definire l’import
|
import ( "database/sql" "fmt" _ "github.com/godror/godror" ) |
Per la connessione al db il comando da usare è Open del package db
|
db, err := sql.Open("godror", "ldc/ldc@localhost:1521/xe") if err != nil { panic(err) } |
Il primo parametro della Open è il nome del driver e a seguire la stringa di connessione verso il db nel formato username@password@ip:port:sid
La funzione restituisce una istanza db e come secondo parametro un oggetto error che potrà essere gestito tramite la funzione panic.
Vediamo subito come effettuare una operazione di scrittura tramite la funzione Exec
|
tx, _ := db.Begin() rowsDeleted, err := db.Exec("delete from audit_obj where id=1") if err != nil { panic(err) } fmt.Println("rowsDeleted: ", rowsDeleted) rowsInserted, err := db.Exec("insert into audit_obj (id, dataora, operazione) values(1, sysdate, 'insert')") if err != nil { panic(err) } fmt.Println("rowsInserted: ", rowsInserted) tx.Commit() |
Nell’esempio tramite la funzione Begin ho avviato una transazione con commit previsto a fine operazioni di scrittura. Nel caso specifico sto facendo la cancellazione di un record dalla tabella di audit e successivo inserimento La funzione Exec ritorna un oggetto Result che rappresenta l’esito di una qualsiasi chiamata al db mostrando quante righe sono state coinvolte e l’id dell’ultimo inserimento.
Se volessi leggere i dati mi viene in aiuto la funzione Query che restituisce un cursore che scorre sulle righe selezionate
|
rows, err := db.Query("select id, dataora, operazione from audit_obj") if err != nil { panic(err) } defer rows.Close() var id int var dataora time.Time var operazione string for rows.Next() { rows.Scan(&id, &dataora, &operazione) fmt.Println(id, dataora, operazione) } db.Close() |
Nell’esempio sto leggenda dalla tabella audit tutti i record e tramite la funzione Scan dell’oggetto Rows la assegna a delle variabili per stamparne successivamente il valore. Con il comando defer chiudo il cursore alla fine di tutte le operazioni.
Per semplificare il lavoro con il db ci vengono in soccorso altri package che consentono di velocizzare il lavoro. Oggi introduco il package sqlx disponibile all’url https://jmoiron.github.io/sqlx/
Per installarlo il comando è
|
go get github.com/jmoiron/sqlx |
ad installazione effettuata può essere importato con la direttiva github.com/jmoiron/sqlx”. Questo package consente di mappare le query direttamente su struct senza dover ricorrere al comando Scan.
|
type Audit struct { ID uint64 `db:"ID"` DATAORA time.Time `db:"DATAORA"` } |
Ho definito una struct Audit che presenta i parametri ID e dataora, ne ho definito il tipo e tramite il thick ho definito il mapping, tramite la regola del contesto:nomecolonna.
A questo punto ottengo il gioco è fatto
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
|
dbx, err := sqlx.Open("godror", "ldc/ldc@localhost:1521/xe") if err != nil { panic(err) } var audit Audit err = dbx.Get(&audit, "select id, dataora from audit_obj where id = 1") if err != nil { panic(err) } fmt.Println(audit) audits := []Audit{} dbx.Select(&audits, "select id, dataora from audit_obj") if err != nil { panic(err) } fmt.Println(audits) |
Con la Open ottengo un riferimento al db che mi espone le funzioni Get per il recupero del singolo oggetto e Select per il recupero di un set di righe,
Alla prossima
ps. per i pigri a seguire l’intero codice
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
|
package main import ( "database/sql" "fmt" "time" _ "github.com/godror/godror" "github.com/jmoiron/sqlx" ) type Audit struct { ID uint64 `db:"ID"` DATAORA time.Time `db:"DATAORA"` } func main() { fmt.Println("Start") db, err := sql.Open("godror", "ldc/ldc@localhost:1521/xe") if err != nil { panic(err) } tx, _ := db.Begin() result, err := db.Exec("delete from audit_obj where id=1") if err != nil { panic(err) } fmt.Println("rowsDeleted: ", result) result, err = db.Exec("insert into audit_obj (id, dataora, operazione) values(1, sysdate, 'insert')") if err != nil { panic(err) } fmt.Println("rowsInserted: ", result) tx.Commit() rows, err := db.Query("select id, dataora, operazione from audit_obj") if err != nil { panic(err) } defer rows.Close() var id int var dataora time.Time var operazione string for rows.Next() { rows.Scan(&id, &dataora, &operazione) fmt.Println(id, dataora, operazione) } db.Close() dbx, err := sqlx.Open("godror", "ldc/ldc@localhost:1521/xe") if err != nil { panic(err) } var audit Audit err = dbx.Get(&audit, "select id, dataora from audit_obj where id = 1") if err != nil { panic(err) } fmt.Println(audit) audits := []Audit{} dbx.Select(&audits, "select id, dataora from audit_obj") if err != nil { panic(err) } fmt.Println(audits) dbx.Close() fmt.Println("End") } |