中文文檔地址:https://jasperxu.github.io/gorm-zh/mysql
英文Doc: https://gorm.io/docs/git
(逐步更新)github
1. 基本操做golang
1)鏈接數據庫sql
鏈接後能夠設置最大鏈接數等參數 數據庫
db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
2) 讀取數據api
讀取數據須要定義struct,經過映射Struct參數與table列的名稱,爲struct對象賦值,列名是Struct參數名的蛇形小寫+下劃線。也能夠加備註`gorm:"column:<new column name>"` ,重設匹配的列名,具體使用例子見下方。數組
a) 指定表名稱:配置struct鏈接table名稱,爲struct配置TableName()方法:app
<definition of your struct>
func (<struct name>) TableName() string { return "<table name>" }
db.Model(&<add struct name here>{})
b) 指定列名稱:(來自手冊): ui
type User struct { ID uint // 列名爲 `id` Name string // 列名爲 `name` Birthday time.Time // 列名爲 `birthday` CreatedAt time.Time // 列名爲 `created_at` } // 重設列名 type Animal struct { AnimalId int64 `gorm:"column:beast_id"` // 設置列名爲`beast_id` Birthday time.Time `gorm:"column:day_of_the_beast"` // 設置列名爲`day_of_the_beast` Age int64 `gorm:"column:age_of_the_beast"` // 設置列名爲`age_of_the_beast` }
c) 如何獲取查詢到的數據?
用api,user能夠是struct的slice或者單一對象:
// 獲取第一條記錄,按主鍵排序 db.First(&user) //// SELECT * FROM users ORDER BY id LIMIT 1; // 獲取最後一條記錄,按主鍵排序 db.Last(&user) //// SELECT * FROM users ORDER BY id DESC LIMIT 1; // 獲取全部記錄 db.Find(&users) //// SELECT * FROM users; // 使用主鍵獲取記錄 / 這個能夠直接用where作。。 db.First(&user, 10) //// SELECT * FROM users WHERE id = 10;
也能夠選擇用Scan將結果掃描到結構體中(變量名要匹配)
type Result struct { Name string Age int } var result Result db.Table("users").Select("name, age").Where("name = ?", 3).Scan(&result)
sql返回多條數據時,能夠將結果掃描進數組,另外一種方式是使用.Rows(),逐行讀取數據。
3)Update
只要執行就update,更新user
db.Save(&user)
也有update方法,若是有篩選條件(where),夾在update前。
db.Model(&user).Update("name", "hello")
其餘update方法能夠check官方文檔
4) 讀鎖
Select for Update
db.First(&model).ForUpdate()
拓展用法:
1. Batch Insert
參考:https://github.com/jinzhu/gorm/issues/255#issuecomment-481159929
type OwnDb struct { *gorm.DB } func (db *OwnDb)BatchInsert(objArr []interface{}) (int64, error) { // If there is no data, nothing to do. if len(objArr) == 0 { return 0, errors.New("insert a slice length of 0") } mainObj := objArr[0] mainScope := db.NewScope(mainObj) mainFields := mainScope.Fields() quoted := make([]string, 0, len(mainFields)) for i := range mainFields { // If primary key has blank value (0 for int, "" for string, nil for interface ...), skip it. // If field is ignore field, skip it. if (mainFields[i].IsPrimaryKey && mainFields[i].IsBlank) || (mainFields[i].IsIgnored) { continue } quoted = append(quoted, mainScope.Quote(mainFields[i].DBName)) } placeholdersArr := make([]string, 0, len(objArr)) for _, obj := range objArr { scope := db.NewScope(obj) fields := scope.Fields() placeholders := make([]string, 0, len(fields)) for i := range fields { if (fields[i].IsPrimaryKey && fields[i].IsBlank) || (fields[i].IsIgnored) { continue } var vars interface{} if (fields[i].Name == "CreatedAt" || fields[i].Name == "UpdatedAt") && fields[i].IsBlank { vars = gorm.NowFunc() } else { vars = fields[i].Field.Interface() } placeholders = append(placeholders, scope.AddToVars(vars)) } placeholdersStr := "(" + strings.Join(placeholders, ", ") + ")" placeholdersArr = append(placeholdersArr, placeholdersStr) // add real variables for the replacement of placeholders' '?' letter later. mainScope.SQLVars = append(mainScope.SQLVars, scope.SQLVars...) } mainScope.Raw(fmt.Sprintf("INSERT INTO %s (%s) VALUES %s", mainScope.QuotedTableName(), strings.Join(quoted, ", "), strings.Join(placeholdersArr, ", "), )) //Execute and Log if err :=mainScope.Exec().DB().Error;err != nil { return 0,err } return mainScope.DB().RowsAffected,nil }
如何用?
db,err := gorm.Open(c.Driver, uri) if err != nil { panic("Database connection failed") } db.LogMode(c.LogMode) DB := &OwnDb{DB:db}
yourDataList := make([]interface{}, len(...)) 向這裏append batchInsert(db, yourDataList)
2. Transaction
一個思路:把rollback寫入defer recover / err中,一旦發生panic就回滾rollback,執行所有命令就commit
// begin a transaction tx := db.Begin() // do some database operations in the transaction (use 'tx' from this point, not 'db') tx.Create(...) // ... // rollback the transaction in case of error tx.Rollback() // Or commit the transaction tx.Commit()
func Transaction(){ conn, tx := NewTransaction(db.Begin()) defer tx.Close() if err := conn.Create(&xxx).Error; err != nil { tx.Fail() } if err := conn.Update(&yyy); err != nil { tx.Fail() } if err := conn.tx.Delete(&zzz); err != nil { tx.Fail() } //add other err you want to handle here }) }