GORM支持了数据库的upsert操作
upsert操作对于插入一条数据而言的,如果插入数据之前,没有这条数据,则会插入该条数据;如果插入数据之前就存在这条数据(索引值),就更新这条记录。
创建结构体
type User struct {gorm.ModelIdentity string `json:"identity" gorm:"uniqueIndex:idx_identity"`Name string `json:"name"`Info string `json:"info"`
}
代码演示
user := models.User{Identity: "zhangsan123",Name: "zhangsan",Info: "zhangsanInfo",
}res := DB.Clauses(clause.OnConflict{Columns: []clause.Column{{Name: "identity"}},DoUpdates: clause.Assignments(map[string]interface{}{"identity": user.Identity, "name": user.Name, "info": user.Info}),
}).Create(&user).Error
if res != nil {log.Printf("UpsertUser Create err:%v\n", res)
} else {log.Printf("UpsertUser Create success\n")
}
数据库新增一条数据
第二次执行
user := models.User{Identity: "zhangsan123",Name: "张三",Info: "mine",
}
数据库更新数据
出现的问题
假设将原来的数据软删除,重新进行修改操作:将名字设置为’李四’,那么是插入一条新的数据还是更新原来数据?
结果发现是直接更新了已经被GORM软删除的数据
原因
究其原因是因为在进行upsert语句的时候需要根据唯一索引(Columns字段)进行更新,由于唯一索引的限制,不能实现插入一条新的数据。
如何实现直接插入一条新的数据而不是更新已经删除的数据:将GORM软删除字段加入并成为一个联合索引。
修改后的结构体
type User struct {gorm.ModelDeletedAt gorm.DeletedAt `json:"-" gorm:"index;uniqueIndex:idx_identity"`Identity string `json:"identity" gorm:"uniqueIndex:idx_identity"`Name string `json:"name"`Info string `json:"info"`
}
代码也要将Columns的条件进行修改
// 定义数据
user := models.User{Identity: "zhangsan123",Name: "张三",Info: "mine",
}res := DB.Clauses(clause.OnConflict{//加上联合索引的所有字段Columns: []clause.Column{{Name: "identity"}, {Name: "deleted_at"}},DoUpdates: clause.Assignments(map[string]interface{}{"identity": user.Identity, "name": user.Name, "info": user.Info}),
}).Create(&user).Error
if res != nil {log.Printf("UpsertUser Create err:%v\n", res)
} else {log.Printf("UpsertUser Create success\n")
}