Golang 連接數據庫 Gorm 使用筆記


中文文檔地址:https://jasperxu.github.io/gorm-zh/

英文Doc: https://gorm.io/docs/

(逐步更新)

1. 基本操作

  1)連接數據庫

          連接后可以設置最大連接數等參數    

  db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")

  2) 讀取數據

    讀取數據需要定義struct,通過映射Struct參數與table列的名稱,為struct對象賦值,列名是Struct參數名的蛇形小寫+下划線。也可以加備注`gorm:"column:<new column name>"`  ,重設匹配的列名,具體使用例子見下方。

    a) 指定表名稱:配置struct連接table名稱,為struct配置TableName()方法:

<definition of your struct>

func (<struct name>) TableName() string { return "<table name>" }
db.Model(&<add struct name here>{})

  b) 指定列名稱:(來自手冊): 

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 }) }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM