首页 > 解决方案 > 如何只编辑数据库中的某些字段而不是全部?

问题描述

我有一个应用程序,并且有一个用于编辑用户信息的端点。但是我发现了一个问题,如果在 json 中看到空白信息(假设用户只想编辑名称,而将其他字段留空),数据将在 DB 中编辑,空白的信息将覆盖是数据库的信息,即使用户不想编辑它们。

如何仅使到达 json 的字段在数据库中得到有效编辑?或者,还有更好的方法?

我很期待知道!

我的控制器

func EditUser(w http.ResponseWriter, r *http.Request) {
    params := mux.Vars(r)
    userID, err := strconv.ParseUint(params["userID"], 10, 64)
    if err != nil {
        returns.ERROR(w, http.StatusInternalServerError, err)
        return
    }

    userIDInToken, err := auth.ExtractUserID(r)
    if err != nil {
        returns.ERROR(w, http.StatusInternalServerError, err)
        return
    }

    if userIDInToken != userID {
        returns.ERROR(w, http.StatusForbidden, errors.New("you can't update other user"))
        return
    }

    bodyRequest, err := ioutil.ReadAll(r.Body)
    if err != nil {
        returns.ERROR(w, http.StatusBadRequest, err)
        return
    }

    var user models.User

    if err := json.Unmarshal(bodyRequest, &user); err != nil {
        returns.ERROR(w, http.StatusUnprocessableEntity, err)
        return
    }

    db, err := db.ConnectToDB()
    if err != nil {
        returns.ERROR(w, http.StatusInternalServerError, err)
        return
    }
    defer db.Close()

    repository := repositories.NewUsersRepository(db)
    if err := repository.UpdateUserInfo(userID, user); err != nil {
        returns.ERROR(w, http.StatusInternalServerError, err)
        return
    }

    returns.JSON_RESPONSE(w, http.StatusOK, nil)

}

我的存储库(访问数据库)

func (repository Users) UpdateUserInfo(userID uint64, user models.User) error {
    stmt, err := repository.db.Prepare(
        "UPDATE user SET name = ?, cpf = ?, email = ?, password = ?, city = ?, state = ? WHERE id = ?")
    if err != nil {
        return err
    }
    defer stmt.Close()

    if _, err := stmt.Exec(
        user.Name,
        user.CPF,
        user.Email,
        user.Password,
        user.City,
        user.State,
        userID,
    ); err != nil {
        return err
    }

    return nil
}

用户型号

type User struct {
    ID       uint64 `json:"id,omitempty"`
    Name     string `json:"name,omitempty"`
    CPF      string `json:"cpf,omitempty"`
    Email    string `json:"email,omitempty"`
    Password string `json:"password,omitempty"`
    City     string `json:"city,omitempty"`
    State    string `json:"state,omitempty"`
}

标签: jsondatabasego

解决方案


我将动态构造 UPDATE 语句以及需要编辑的字段切片,方法是在将字段添加到切片之前检查字段是否不为空。

像这样的东西:

func (repository Users) UpdateUserInfo(userID uint64, user User) error {
    fields := make([]string, 0)
    values := make([]string, 0)

    if user.Name != "" {
        values = append(values, user.Name)
        fields = append(fields, "name = ?")
    }
    if user.CPF != "" {
        values = append(values, user.CPF)
        fields = append(fields, "cpf = ?")
    }
    if user.Email != "" {
        values = append(values, user.Email)
        fields = append(fields, "email = ?")
    }
    if user.Password != "" {
        values = append(values, user.Password)
        fields = append(fields, "password = ?")
    }
    if user.City != "" {
        values = append(values, user.City)
        fields = append(fields, "city = ?")
    }
    if user.State != "" {
        values = append(values, user.State)
        fields = append(fields, "state = ?")
    }

    if len(fields) != 0 {
        return errors.New("no fields to update")
    }

    updateString := fmt.Sprintf("UPDATE user SET %s WHERE id = ?", strings.Join(fields, ","))
    stmt, err := repository.db.Prepare(updateString)
    if err != nil {
        return err
    }
    defer stmt.Close()

    if _, err := stmt.Exec(values...,userID); err != nil {
        return err
    }

    return nil
}

对于更简洁的代码,我建议可能将“if 语句”/验证提取到单独的函数中。


推荐阅读