以前、Go言語で使えるmigrationライブラリを紹介しました。今回はORMライブラリを紹介します。
Go言語のORMライブラリを2つ紹介します。これらのライブラリを使用することで、DBのデータをstructにマッピングすることができます。それでは、各ライブラリの特徴を簡単に紹介します。
GORMは「Full-Featured ORM」や「Developer Friendly」を謳う非常に多機能な定番ORMで、これ単体で一通りのことができます。また、ドキュメントも豊富です。
GORMの機能を以下に列挙します。
SQLBoilerは非常にパフォーマンスの高いORMのようです。migration機能はないので、goose、 sql-migrateや前回紹介したsqldefなどを併用する必要があります。SQLBoilerの使い方についてはこちらが参考になります。
それでは、実際にGORMを使ってみます。
下記の通りインストールします。
$ go get -u github.com/jinzhu/gorm
今回はMySQLを使用しますので、こちらもインストールしておきます。
$ go get -u github.com/go-sql-driver/mysql
nameというフィールドを持つUsersというテーブルを定義します。下記のようにgorm.Modelと記述するとcreated_at、updated_at、deleted_atが定義されます。
type User struct { gorm.Model Name string }
マイグレーションは下記のように行います。
?parseTime=trueを記述しないと「unsupported Scan, storing driver.Value type []uint8 into type *time.Time」というエラーが発生します。こちらの通りDB側の型とGo言語側の型が違うことで発生するようです。
// user_name:password@host/database_name db, err := gorm.Open("mysql", "root:root@tcp(127.0.0.1:3306)/gorm_test?parseTime=true") if err != nil { panic("failed to connect } defer db.Close() db.AutoMigrate(&User{}) if db.Error != nil { panic(db.Error) }
実際のテーブルは下記のとおりです。
mysql> desc users; +------------+------------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +------------+------------------+------+-----+---------+----------------+ | id | int(10) unsigned | NO | PRI | NULL | auto_increment | | created_at | timestamp | YES | | NULL | | | updated_at | timestamp | YES | | NULL | | | deleted_at | timestamp | YES | MUL | NULL | | | name | varchar(255) | YES | | NULL | | +------------+------------------+------+-----+---------+----------------+
insertは下記のように行います。
var newUser = &User{Name: "Yamada"} db = db.Create(newUser) if db.Error != nil { panic(db.Error) }
selectは下記のように行います。
var user User db.First(&user, "name = ?", "Yamada") if db.Error != nil { panic(db.Error) }
updateは下記のように行います。
var user User db.First(&user, "name = ?", "Yamada") if db.Error != nil { panic(db.Error) } user.Name = "Tanaka" db.Save(&user)
deleteは下記のように行います。
var user User db.First(&user, "name = ?", "Yamada") if db.Error != nil { panic(db.Error) } db.Delete(&user) if db.Error != nil { panic(db.Error) }
CRUD操作のサンプルコードは下記のとおりです。
package main import ( "encoding/json" "fmt" "github.com/jinzhu/gorm" _ "github.com/jinzhu/gorm/dialects/mysql" ) type User struct { gorm.Model Name string } func main() { db, err := gorm.Open("mysql", "root:root@tcp(127.0.0.1:3306)/gorm_test?parseTime=true") if err != nil { panic("failed to connect database") } defer db.Close() db.LogMode(true) var newUser = &User{Name: "Yamada"} db.AutoMigrate(&User{}) if db.Error != nil { panic(db.Error) } db = db.Create(newUser) if db.Error != nil { panic(db.Error) } j, _ := json.Marshal(newUser) fmt.Println(string(j)) var user User db.First(&user, "name = ?", "Yamada") if db.Error != nil { panic(db.Error) } j, _ = json.Marshal(user) fmt.Println(string(j)) user.Name = "Tanaka" db.Save(&user) db.First(&user, "name = ?", "Tanaka") if db.Error != nil { panic(db.Error) } j, _ = json.Marshal(user) fmt.Println(string(j)) db.Delete(&user) if db.Error != nil { panic(db.Error) } }
実行時のログは下記のとおりです。
$ go run main.go (/Users/***/dev/src/test_gorm/main.go:29) [2018-11-18 12:07:38] [1.01ms] INSERT INTO `users` (`created_at`,`updated_at`,`deleted_at`,`name`) VALUES ('2018-11-18 12:07:38','2018-11-18 12:07:38',NULL,'Yamada') [1 rows affected or returned ] {"ID":9,"CreatedAt":"2018-11-18T12:07:38.099754+09:00","UpdatedAt":"2018-11-18T12:07:38.099754+09:00","DeletedAt":null,"Name":"Yamada"} (/Users/***/dev/src/test_gorm/main.go:38) [2018-11-18 12:07:38] [0.58ms] SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL AND ((name = 'Yamada')) ORDER BY `users`.`id` ASC LIMIT 1 [1 rows affected or returned ] {"ID":9,"CreatedAt":"2018-11-18T03:07:38Z","UpdatedAt":"2018-11-18T103:07:38Z","DeletedAt":null,"Name":"Yamada"} (/Users/***/dev/src/test_gorm/main.go:47) [2018-11-18 12:07:38] [0.40ms] UPDATE `users` SET `created_at` = '2018-11-18 18:07:38', `updated_at` = '2018-11-18 12:07:38', `deleted_at` = NULL, `name` = 'Tanaka' WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = '9' [1 rows affected or returned ] (/Users/***/dev/src/test_gorm/main.go:49) [2018-11-18 12:07:38] [0.40ms] SELECT * FROM `users` WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = '9' AND ((name = 'Tanaka')) ORDER BY `users`.`id` ASC LIMIT 1 [1 rows affected or returned ] {"ID":9,"CreatedAt":"2018-11-18T03:07:38Z","UpdatedAt":"2018-11-18T03:07:38Z","DeletedAt":null,"Name":"Tanaka"} (/Users/***/dev/src/test_gorm/main.go:57) [2018-11-18 12:07:38] [0.40ms] UPDATE `users` SET `deleted_at`='2018-11-18 12:07:38' WHERE `users`.`deleted_at` IS NULL AND `users`.`id` = '9' [1 rows affected or returned ]
今回はGo言語でのORMライブラリを紹介しました。今回はGORMを使ってみましたが、SQLBoilerも実際に動かしてみたいと思います。
なお、Go言語に関してはこちらでも多くの記事を紹介していますので、ぜひご覧ください。