Предложение GORM OnConflict не учитывает версию optimisticLock

При использовании предложения OnConflict я устанавливаю флаг UpdateAll на true. В моей таблице также есть поле VersionoptmisticLock.Version.

Я ожидаю, что gorm обновит все столбцы, включая столбец версии, до новой версии в случае конфликта, но версия не обновляется автоматически.

Пример:

type TestEntity struct {
  ID string `gorm:varchar(100);primary_key`
  Name string
  Version optimisticlock.Version
}

Таблица имеет одну строку с записями:

ID: "xyz", Name: "first", Version: 1

Я хочу обновить текущую строку:

testUpdateEntity := &TestEntity{
  ID: "xyz",
  Name: "second",
}

Когда я бегу:

dres := u.db.WithContext(context.TODO()).Clauses(clause.OnConflict{
        UpdateAll: true,
    }).Create(testUpdateEntity)

Затем он должен самостоятельно обновить версию до 2 после обнаружения конфликта.

  • Я не хочу упоминать каждый столбец с помощью DoUpdates, потому что в реальной таблице есть несколько столбцов.
  • Это случай необработки оптимистического поведения блокировки с помощью предложений?
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
1
0
277
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Насколько мне известно, GORM в настоящее время не поддерживает автоматическое обновление столбца версии оптимистической блокировки при использовании предложения OnConflict.

Когда вы используете предложение OnConflict с UpdateAll, GORM генерирует оператор UPSERT, который пытается вставить новую строку, и в случае возникновения конфликта обновляет все столбцы существующей строки значениями из новой строки. Однако в этом сценарии GORM не обрабатывает автоматически столбец версии оптимистической блокировки.

Чтобы обработать столбец версии оптимистической блокировки в этой ситуации, вы можете явно указать столбцы для обновления, используя предложение DoUpdates.

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

// Define a function to get a list of columns to update excluding primary key and version
func getColumnsToUpdate(db *gorm.DB, entity interface{}) ([]string, error) {
    var columnsToUpdate []string

    // Retrieve table name
    tableName := db.NamingStrategy.TableName("", db.Statement.Schema.Table)

    // Retrieve column names
    columnNames, err := db.Migrator().Columns(tableName)
    if err != nil {
        return nil, err
    }

    // Exclude primary key and version columns
    for _, columnName := range columnNames {
        if columnName != "ID" && columnName != "Version" {
            columnsToUpdate = append(columnsToUpdate, columnName)
        }
    }

        return columnsToUpdate, nil
    
    }

затем обновите свой запрос

// Define update data
updateData := make(map[string]interface{})
for _, column := range columnsToUpdate {
    updateData[column] = "updated_value" // Set your updated value here
}

// Add version update
updateData["Version"] = gorm.Expr("Version + 1")

// Apply update with OnConflict clause
dres := u.db.WithContext(context.TODO()).Clauses(clause.OnConflict{
    UpdateAll: true,
}).Model(&TestEntity{}).Where("id = ?", testUpdateEntity.ID).Updates(updateData)

Но в этом случае версия не будет постоянно обновляться. Допустим, две транзакции происходят одновременно, теперь в запросе должен присутствовать оператор версии version=version+1.

hatake kakashi 15.04.2024 10:48

Также в настоящее время в методах Save() и Update() gorm не выдает OptimisticlockVersion.

hatake kakashi 15.04.2024 10:48

Я только что обновил пример кода, чтобы увеличить версию при обновлении данных.

Long.NTV 15.04.2024 11:12

Спасибо за ответ. Это работает для случая обновления. Но я заметил одну вещь: gorm не выдает никаких ошибок, если одна транзакция не может обновиться из-за optmisticlock или даже если запись не найдена (когда версия уже увеличена).

hatake kakashi 15.04.2024 14:51

Другие вопросы по теме