go語言beego架構 orm實現insertOrUpdate功能

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

在beego1.6.1版本orm中並未提供insertOrUpdate,但是自己做項目時遇到了這個需求,顧寫了一個自己的實現,暫只支援mysql與postgres。實現原理是資料內建可實現insertorupdate的功能語句。
mysql:-ON DUPLICATE KEY UPDATE
postgres : -ON CONFLICT DO UPDATE SET
然後去orm實現中自己拼裝sql語句

好了,亮代碼:

func (d *dbBase) InsertOrUpdate(q dbQuerier, mi *modelInfo,ind reflect.Value, tz *time.Location, dn string, args …string)
(int64, error) {

iouStr := ""mysql := "mysql"postgres := "postgres"argsMap := map[string]string{}if dn == mysql {    iouStr = "ON DUPLICATE KEY UPDATE"} else if dn == postgres && len(args) > 0 {    args0 = args[0]    iouStr = fmt.Sprintf("ON CONFLICT (%s) DO UPDATE SET", args0)} else {    return 0, fmt.Errorf("`%s` nonsupport insert or update in beego", dn)}for _, v := range args {    kv := strings.Split(v, "=")    if len(kv) == 2 {        argsMap[kv[0]] = kv[1]    }}isMulti := falsenames := make([]string, 0, len(mi.fields.dbcols)-1)Q := d.ins.TableQuote()values, err := d.collectValues(mi, ind, mi.fields.dbcols, true, true, &names, tz)if err != nil {    return 0, errmarks := make([]string, len(names))updateValues := make([]interface{}, 0)updates := make([]string, len(names))var conflitValue interface{}for i, v := range names {    marks[i] = "?"    valueStr := argsMap[v]    if v == args0 {        conflitValue = values[i]    }    if valueStr != "" {        switch dn {        case mysql:            updates[i] = v + "=" + valueStr            break        case postgres:            if conflitValue != nil {        updates[i] = fmt.Sprintf("%s=(select %s from %s where %s = ? )", v, valueStr, mi.table, args[0])                updateValues = append(updateValues, conflitValue)            } else {                return 0, fmt.Errorf("`%s` must be in front of `%s` in your struct", args[0], v)            }            break        }    } else {        updates[i] = v + "=?"        updateValues = append(updateValues, values[i])    }values = append(values, updateValues...)sep := fmt.Sprintf("%s, %s", Q, Q)qmarks := strings.Join(marks, ", ")qupdates := strings.Join(updates, ", ")columns := strings.Join(names, sep)multi := len(values) / len(names)if isMulti {    qmarks = strings.Repeat(qmarks+"), (", multi-1) + qmarks}query := fmt.Sprintf("INSERT INTO %s%s%s (%s%s%s) VALUES (%s) %s "+qupdates, Q, mi.table, Q, Q, columns, Q, qmarks, iouStr)if isMulti || !d.ins.HasReturningID(mi, &query) {    res, err := q.Exec(query, values...)    if err == nil {        if isMulti {            return res.RowsAffected()        }        return res.LastInsertId()    }    return 0, err}row := q.QueryRow(query, values...)var id int64err = row.Scan(&id)return id, err}

這就是實現功能的全部邏輯,當然要想在beego orm中使用insertorupdate還有一些其他的工作要做,首先這段代碼應該添加在-beego/orm檔案夾下的db.go檔案中

然後在orm.go檔案中添加
func (o *orm) InsertOrUpdate(md interface{},colConflitAndArgs …string) (int64, error) {

mi, ind := o.getMiInd(md, true)id, err := o.alias.DbBaser.InsertOrUpdate(o.db, mi, ind, o.alias.TZ, o.alias.DriverName, colConflitAndArgs...)if err != nil {    return id, err    }o.setPk(mi, ind, id)return id, nil}

再在types.go檔案中的type Ormer interface和type dbBaser interface中分別添加

**InsertOrUpdate(md interface{}, colConflitAndArgs ...string) (int64, error)
**InsertOrUpdate(dbQuerier, *modelInfo, reflect.Value, *time.Location, string, ...string) (int64, error)

好了,現在大功告成了。可以使用InssertOrUpdate功能了

列如:

mysql:

func IOUFinish(all *Finish) int64 {

db := orm.NewOrm()db.Using("mysql")r, e := db.InsertOrUpdate(all, "step=step+1")if e != nil {    fmt.Println(e)    return 0}fmt.Println(r)return r}

這個函數在出入資料時有主鍵或者唯一鍵衝突,將執行update操作,其中step列執行+自增操作,其他列按model中的值進行update操作。其中”step=step+1”格式資料可以有多個也可以沒有,這種格式只用於自增操作

postgres:

func IOUFinish(all *Finish) int64 {

db := orm.NewOrm()db.Using("postgres")r, e := db.InsertOrUpdate(all,"confilctColumnName" "step=step+1")if e != nil {    fmt.Println(e)    return 0}fmt.Println(r)return r}

當操作postgres資料庫是,必須在model後的第一個參數指定你預期的衝突列的列名(由於實現此功能的sql語句需要且資料庫版本必須大於9.5,因為實現的語句由9.5版本推出),其他與mysql一致。

提示:在使用自增操作是最好不要自增主鍵或者唯一鍵,可能會引起錯誤。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.