Как сохранить объект в БД только в случае изменения определенных полей, но не других? - PullRequest
0 голосов
/ 05 июля 2019

Это кажется простым вопросом, но у меня есть некоторые структуры, которые являются довольно большими и имеют много полей. Я хочу сделать запрос к базе данных только , если некоторые поля изменились, но не если другие изменились, поскольку они вообще не сохраняются, и даже отправлять этот запрос в базу данных или делать какие-либо другой необходимой логики в моем приложении - пустая трата времени. Пример :

type Example struct {
    PersistedField1  string `json:"pf1"`
    PersistedField2  string `json:"pf2"`
    PersistedField3  string `json:"pf3"`
    UnpersistedField string `json:"uf"`
}

Я хочу, чтобы Пример сохранялся только в том случае, если изменилось одно из первых 3 полей, но не в том случае, если изменилось последнее (которое в любом случае не сохраняется в БД)

Я не хочу проверять каждое поле отдельно перед отправкой в ​​базу данных, поэтому мое текущее решение - добавить метод .Equal() в структуру:

func (e Example) Equal(e2 Example) bool {
    return cmp.Equal(e.PersistedField1, e2.PersistedField1) && 
        cmp.Equal(e.PersistedField2, e2.PersistedField2) && 
        cmp.Equal(e.PersistedField3, e2.PersistedField3)
}

Затем выполните cmp.Equal() перед тем, как делать что-нибудь дБ.

if cmp.Equal(oldE, newE) {
    log.Println("some debug msg")
    return
}

Я хочу улучшить это решение, потому что его довольно сложно поддерживать. Это .Equal() растет слишком сильно с большей структурой.

Можно ли использовать какие-то теги для каждого поля в структуре, чтобы помочь в сравнении?

1 Ответ

0 голосов
/ 08 июля 2019

Решение оказалось проще, чем я думал, и не требовало использования тегов, как я изначально думал.

Я добавил новый .Equals() метод:

func (e *Example) Equals(e2 *Example) bool {
    unexportedFieldsOpt := cmp.AllowUnexported(Example{})
    fieldsToIgnore := cmpopts.IgnoreFields(Example{}, "UnpersistedField")
    return cmp.Equal(e, e2, unexportedFieldsOpt, fieldsToIgnore)
}

Это приводит к нормальному сравнению с использованием cmp.Equal(), но некоторые поля игнорируются при сравнении, т. Е. Поля, которые не сохраняются в базе данных, и поэтому нам не нужно знать, изменились ли они.

Это лучшее решение, потому что мне больше не нужно редактировать метод каждый раз, когда структура получает новое поле, если только это поле не сохраняется. Кроме того, код намного аккуратнее и не продолжает расти по мере увеличения числа полей в структуре, в отличие от исходного примера в моем вопросе.

Он использует отражение, но кажется, что это было неизбежно, даже если я что-то сделал с тегами.

Я переименовал его из .Equal(), потому что cmp.Equal(e1, e2) автоматически ищет собственный метод .Equal(), который будет использоваться для сравнения, но мой также вызывает cmp.Equal(e1, e2), так что это вызовет бесконечную рекурсию.

...