更新包含在有效负载中的列

时间:2017-10-19 08:00:05

标签: mysql rest go

我有一个结构映射到mysql表,如下所示,并希望更新在PUT请求有效负载中发送的字段

type Notification struct {
 Id                 int64     `json:"id"`
 Type               NotificationType
 Subject            string    `json:"confidence"`
 Body               string    `json:"body"`
 CreatedDate        time.Time `json:"created_dt"`
 CreatedBy          int64     `json:"created_by"`
 ParentNotification int64     `json:"parent_id"`
 IsExpired          bool      `json:"expired"`
}

目前我要求所有字段都包含在有效负载中,即使数据未更改并使用 db.Exec(query)语句使用查询更新所有列。

有什么方法可以让客户只包含有效负载中更改的字段并仅更新这些字段?

{
 "body" : "new body"
 "subject" : "new subject"
}

我正在使用db side中的以下软件包。

"database/sql"
_ "github.com/go-sql-driver/mysql"

2 个答案:

答案 0 :(得分:1)

一种做你想做的事情,就是让客户只发送他们想要改变的数据,就是要有一个额外的" param"每个类型" db表"类型。因此,例如,根据您的Notification类型,您将拥有NotificationParams类型,如下所示:

type NotificationParams struct {
    Id      int64 `json:"id"`
    // use pointers so that a field that is not present in the json
    // will result in a nil pointer value, which tells you that no
    // update is needed for that column, it also allows the client
    // to send an empty string if they want to delete the content of
    // some column, e.g. Body.
    Type    *NotificationType
    Subject *string `json:"confidence"`
    Body    *string `json:"body"`
    // and other fields that you want to allow the client change
}

然后在你的处理程序或者你可以沿着这些方向做点什么:

params := &NotificationParams{} // unmarshal from json
notif := &Notification{} // read from db using params.Id

// change only those fields that were provided
if params.Type != nil {
    notif.Type = *params.Type
}
if params.Subject != nil {
    notif.Subject = *params.Subject
}
if params.Body != nil {
    notif.Body = *params.Body
}

// do some validation...

// if ok save notif using mysql UPDATE

更新

如果你想避免编写大量的if语句,你可以编写几个" setter"或者"申请"功能(您更喜欢哪个名称)为您执行此操作,每个类型对应您支持的功能,例如:一个用于string,一个用于time.Time等等。

以此功能为例:

// The variadic list of functions can be used to transform (think
// sanitization, normalization, etc.) the value before setting
// it to the dst pointer.
func ApplyStr(dst, src *string, fns ...func(string) string) {
    if src != nil {
        s := *src
        for _, fn := range fns {
            s = fn(s)
        }

        *dst = s
    }
}

然后你会使用像this playground example这样的函数。

答案 1 :(得分:0)

以下方法使用GORM库在收到有效负载后保留数据:

package main

import (
    "github.com/jinzhu/gorm"
    _ "github.com/jinzhu/gorm/dialects/mysql"
    "time"
)


type NotificationType struct {
    gorm.Model

}

type Notification struct {
    gorm.Model
    Id                 int64     `json:"id"`
    Type               NotificationType
    Subject            string    `json:"confidence"`
    Body               string    `json:"body"`
    CreatedDate        time.Time `json:"created_dt"`
    CreatedBy          int64     `json:"created_by"`
    ParentNotification int64     `json:"parent_id"`
    IsExpired          bool      `json:"expired"`
}

func main() {
    //your handler code to receive and decode payload from client


    //save data to database
    db, err := gorm.Open("mysql", "user:password@/dbname?charset=utf8&parseTime=True&loc=Local")
    if err != nil {
        panic("failed to connect database")
    }
    defer db.Close()

    // Migrate the schema
    db.AutoMigrate(&Notification{})

    // Read
    var Notification notification
    db.First(&notification, 1) // find notification with id 1 , the id from your payload

    // Update the table from notification object
    db.Save(&notification)
}