英文:
How to edit only some fields in the database instead of all?
问题
我有一个使用Go语言编写的应用程序,其中有一个用于编辑用户信息的端点。但我发现一个问题,如果在JSON中看到空白信息(假设用户只想编辑姓名,并将其他字段留空),数据将在数据库中被编辑,并且空白的信息将覆盖数据库中的信息,即使用户不想编辑它们。
我该如何使只有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"`
}
英文:
I have an application in go, and there is an endpoint for editing user information. But I found a problem, if in json it sees blank information (let's assume the user just wants to edit the name, and leaves the other fields blank), the data will be edited in the DB and the information that came blank will overwrite the information that are DB, even if the user didn't want to edit them.
How can I make only the fields that arrive in json to be effectively edited in the DB? Or is there a better way?
I'm looking forward to knowing!
My controller
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)
}
My repository (that access DB)
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
}
Model for user
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"`
}
答案1
得分: 0
我会动态构建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(append(values, userID)...); err != nil {
return err
}
return nil
}
为了使代码更清晰,我建议将"if语句"和验证提取到一个单独的函数中。
英文:
I would dynamically construct the UPDATE statement as well as a slice of the fields that need to be edited by checking if the field is not empty before adding it to the slice.
Something like this:
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
}
For cleaner code, I'd recommend maybe extracting the "if statements"/validation into a separate function.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论