はじめに
sqlxというライブラリを使ってみたのでメモ。
sqlxとは
標準ライブラリdatabase/sql
の拡張ライブラリです。
database/sql
では、DBからとってきたデータをカラムごとにScan(型変換)して構造体にマッピングする必要があるのですが、カラム数が多いとこの部分の記述が非常に苦痛です。
この面倒な作業を勝手にやってくれたりするのがsqlx
の役割です。
↓database/sql
を使った場合のScan処理の例
customerRepositoryDb.go
type CustomerRepositoryDb struct {
client *sql.DB
}
func (d CustomerRepositoryDb) FindAll() ([]Customer, error) {
findAllSql := "select customer_id, name, city, zipcode, date_of_birth, status from customers"
rows, err := d.client.Query(findAllSql)
if err != nil {
logger.Error("Error while querying customer table " + err.Error())
return nil, err
}
customers := make([]Customer, 0)
for rows.Next() {
var c Customer
err := rows.Scan(&c.Id, &c.Name, &c.City, &c.Zipcode, &c.DateofBirth, &c.Status)
if err != nil {
logger.Error("Error while scanning customers " + err.Error())
return nil, err
}
customers = append(customers, c)
}
return customers, nil
}
実装
以下がsqlx
で同じ処理を記述したコードです。
database/sql
だとあったクエリとScan処理の記述が、なんとerr = d.client.Select(&customers, findAllSql)
の一行で完結します。
customerRepositoryDb.go
type CustomerRepositoryDb struct {
client *sqlx.DB
}
func (d CustomerRepositoryDb) FindAll() ([]Customer, error) {
var err error
customers := make([]Customer, 0)
findAllSql := "select customer_id, name, city, zipcode, date_of_birth, status from customers"
err = d.client.Select(&customers, findAllSql)
if err != nil {
logger.Error("Error while querying customer table " + err.Error())
return nil, err
}
return customers, nil
}
また、名前付きクエリの場合には、err := d.client.Get(&c, customerSql, id)
のように、GETメソッドを使用することができます。
func (d CustomerRepositoryDb) ById(id string) (*Customer, *errs.AppError) {
customerSql := "select customer_id, name, city, zipcode, date_of_birth, status from customers where customer_id = ?"
var c Customer
err := d.client.Get(&c, customerSql, id)
if err != nil {
if err == sql.ErrNoRows {
return nil, errs.NewNotFoundError("customer not found")
} else {
logger.Error("Error while scanning customer " + err.Error())
return nil, errs.NewUnexpectedError("unexpected database error")
}
}
return &c, nil
}
参考資料