GORM не обновляет логическое поле до false

На updates gorm не обновляет логический тип до false. По умолчанию он обновляется до true, но когда я пытаюсь обновить до false, не меняется. Ошибок тоже не вижу. В чем может быть проблема?

type Attendee struct {
    ID             uint   `gorm:"primary_key" gorm:"AUTO_INCREMENT" json:"id,omitempty" mapstructure:"id" csv:"ID"`
    Email          string `json:"email,omitempty" mapstructure:"email" csv:"Email,required"`

    ShowDirectory  bool   `json:"show_directory,omitempty" gorm:"default:true" mapstructure:"show_directory" csv:"-"`
}


var attendee Attendee
// JSON.unmarshal lines here for the &attendee
if err := service.DB.Model(&attendee).Updates(Attendee{
        Email:         attendee.Email,
        ShowDirectory: false
}).Error; err != nil {
    return Attendee{}, err
}

Альтернативное решение:

Это работает, но я обновляю несколько атрибутов. Итак, я не могу это использовать.

    att := Attendee{ID: 1}
    service.DB.Model(&att).Update("ShowDirectory", false)

person 7urkm3n    schedule 18.06.2019    source источник
comment
Это задокументированное и предполагаемое поведение при использовании структур, вы можете использовать карту для свойств, на которые влияет такое странное (IMO) дизайнерское решение. gorm.io/docs/update.html#Update-Changed-Fields (обратите внимание на комментарии)   -  person mkopriva    schedule 18.06.2019
comment
@mkopriva ohhh, спасибо, только что заметил. Он говорит false are blank values of their types об использовании структуры   -  person 7urkm3n    schedule 18.06.2019


Ответы (4)


Как упоминалось в @mkopriva, Документация GORM

// Update attributes with `struct`, will only update non-zero fields
db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 > 21:34:10' WHERE id = 111;

// Update attributes with `map`
db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

ПРИМЕЧАНИЕ. При обновлении с помощью структуры GORM будет обновлять только ненулевые поля, вы можете использовать map для обновления атрибутов или использовать Select, чтобы указать поля для обновления

Решено:

if err := service.DB.Model(&attendee).Updates(map[string]interface{}{
    "Email":          attendee.Email,
    "ShowDirectory": false
}).Error; err != nil {
    return Attendee{}, err
}
person 7urkm3n    schedule 18.06.2019

Еще один удобный способ - сделать это поле указателем.

ПРИМЕЧАНИЕ: все поля с нулевым значением, например 0, '', false или другими нулевыми значениями, не будут сохранены в базе данных, но будут использовать свое значение по умолчанию. Если вы хотите избежать этого, рассмотрите возможность использования типа указателя или сканера / оценщика Ссылка

В вашем случае модель будет выглядеть так:

type Attendee struct {
ID             uint   `gorm:"primary_key" gorm:"AUTO_INCREMENT" json:"id,omitempty" mapstructure:"id" csv:"ID"`
Email          string `json:"email,omitempty" mapstructure:"email" csv:"Email,required"`

ShowDirectory  *bool   `json:"show_directory,omitempty" gorm:"default:true" mapstructure:"show_directory" csv:"-"`

}

person pramod    schedule 03.07.2020

Вы должны написать тип gorm в своей структуре, примерно так: gorm:"type:boolean; column:column_name", и он обязательно будет работать!

person DragoRoff    schedule 15.08.2019
comment
проверьте документацию, там написано false are blank values of their types, а пустое значение всегда false - person 7urkm3n; 15.08.2019
comment
Я попробую в следующий раз, когда столкнусь с этим :) - person 7urkm3n; 15.08.2019

Не используйте структуру go для обновления ненулевых полей, таких как boolean: false

Приведенный ниже код не будет обновлять Active: false в вашей базе данных, и gorm просто игнорирует

db.Model(&user).Updates(User{Name: "hello", Age: 18, Active: false})
// UPDATE users SET name='hello', age=18, updated_at = '2013-11-17 21:34:10' WHERE id = 111;

Приведенный ниже код обновит Active: false

db.Model(&user).Updates(map[string]interface{}{"name": "hello", "age": 18, "actived": false})
// UPDATE users SET name='hello', age=18, actived=false, updated_at='2013-11-17 21:34:10' WHERE id=111;

Используйте карту вместо структуры go

person Narendranath Reddy    schedule 03.11.2020
comment
Вы видели мой ответ? А какая разница между моими? - person 7urkm3n; 04.11.2020
comment
Вы сказали, что без четкого объяснения и лучшего примера и сравнения, я просто добавил дополнительные объяснения. Вы знаете, что я столкнулся с той же проблемой и подошел к этому вопросу, но ваш ответ не помог, когда я впервые увидел ваш ответ, когда я увидел реальную разницу с первого взгляда, поверьте мне, для нескольких пользователей мой ответ поможет и содержит хорошее объяснение, поэтому Решил написать еще один ответ. Спасибо за ответ - person Narendranath Reddy; 04.11.2020