這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
項目地址:https://github.com/eaigner/hood
這是一個極具美感的ORM庫。
特性
- 鏈式的api
- 事務支援
- 遷移和名字空間產生
- 模型變數
- 模型時間
- 資料庫方言介面
- 沒有含糊的欄位
- 乾淨可測試的代碼
開啟資料庫
如果方言已經註冊可以直接開啟資料庫
hd, err := hood.Open("postgres", "user= dbname=")
你也可以開啟資料庫時候指定方言
hd := hood.New(db, NewPostgres())
Schemas
你可以這樣聲明
type Person struct { // Auto-incrementing int field 'id' Id hood.Id // Custom primary key field 'first_name', with presence validation FirstName string `sql:"pk" validate:"presence"` // string field 'last_name' with size 128, NOT NULL LastName string `sql:"size(128),notnull"` // string field 'tag' with size 255, default value 'customer' Tag string `sql:"size(255),default('customer')"` // You can also combine tags, default value 'orange' CombinedTags string `sql:"size(128),default('orange')"` Birthday time.Time // timestamp field 'birthday' Data []byte // data field 'data' IsAdmin bool // boolean field 'is_admin' Notes string // text field 'notes' // You can alternatively define a var char as a string field by setting a size Nick string `sql:"size(128)"` // Validates number range Balance int `validate:"range(10:20)"` // These fields are auto updated on save Created hood.Created Updated hood.Updated // ... and other built in types (int, uint, float...)} // Indexes are defined via the Indexed interface to avoid// polluting the table fields. func (table *Person) Indexes(indexes *hood.Indexes) { indexes.Add("tag_index", "tag")// params: indexName, unique, columns... indexes.AddUnique("name_index", "first_name", "last_name")}
資料移轉
你要先安裝hood tool ,然後運行
go get github.com/eaigner/hoodcd $GOPATH/src/github.com/eaigner/hood./install.sh<
例子
下面是一個使用例子
package main import ( "hood") func main() { // Open a DB connection, use New() alternatively for unregistered dialects hd, err := hood.Open("postgres", "user=hood dbname=hood_test sslmode=disable") if err != nil { panic(err) } // Create a table type Fruit struct { Id hood.Id Name string `validate:"presence"` Color string } err = hd.CreateTable(&Fruit{}) if err != nil { panic(err) } fruits := []Fruit{ Fruit{Name: "banana", Color: "yellow"}, Fruit{Name: "apple", Color: "red"}, Fruit{Name: "grapefruit", Color: "yellow"}, Fruit{Name: "grape", Color: "green"}, Fruit{Name: "pear", Color: "yellow"}, } // Start a transaction tx := hd.Begin() ids, err := tx.SaveAll(&fruits) if err != nil { panic(err) } fmt.Println("inserted ids:", ids)// [1 2 3 4 5] // Commit changes err = tx.Commit() if err != nil { panic(err) } // Ids are automatically updated if fruits[0].Id != 1 || fruits[1].Id != 2 || fruits[2].Id != 3 { panic("id not set") } // If an id is already set, a call to save will result in an update fruits[0].Color = "green" ids, err = hd.SaveAll(&fruits) if err != nil { panic(err) } fmt.Println("updated ids:", ids)// [1 2 3 4 5] if fruits[0].Id != 1 || fruits[1].Id != 2 || fruits[2].Id != 3 { panic("id not set") } // Let's try to save a row that does not satisfy the required validations _, err = hd.Save(&Fruit{}) if err == nil || err.Error() != "value not set" { panic("does not satisfy validations, should not save") } // Find // // The markers are db agnostic, so you can always use '?' // e.g. in Postgres they are replaced with $1, $2, ... var results []Fruit err = hd.Where("color", "=", "green").OrderBy("name").Limit(1).Find(&results) if err != nil { panic(err) } fmt.Println("results:", results)// [{1 banana green}] // Delete ids, err = hd.DeleteAll(&results) if err != nil { panic(err) } fmt.Println("deleted ids:", ids)// [1] results = nil err = hd.Find(&results) if err != nil { panic(err) } fmt.Println("results:", results)// [{2 apple red} {3 grapefruit yellow} {4 grape green} {5 pear yellow}] // Drop hd.DropTable(&Fruit{})}