Save方法在没有pk的时候是insert,有pk的时候是update,当update时,如果Error == nil && RowsAffected == 0,则先select,如果result.RecordNotFound() == true则insert,如果Error == nil则update。

    1. // Save update value in database, if the value doesn't have primary key, will insert it
    2. func (s *DB) Save(value interface{}) *DB {
    3. scope := s.NewScope(value)
    4. if !scope.PrimaryKeyZero() {
    5. newDB := scope.callCallbacks(s.parent.callbacks.updates).db
    6. if newDB.Error == nil && newDB.RowsAffected == 0 {
    7. return s.New().Table(scope.TableName()).FirstOrCreate(value)
    8. }
    9. return newDB
    10. }
    11. return scope.callCallbacks(s.parent.callbacks.creates).db
    12. }
    1. // FirstOrCreate find first matched record or create a new one with given conditions (only works with struct, map conditions)
    2. // https://jinzhu.github.io/gorm/crud.html#firstorcreate
    3. func (s *DB) FirstOrCreate(out interface{}, where ...interface{}) *DB {
    4. c := s.clone()
    5. if result := s.First(out, where...); result.Error != nil {
    6. if !result.RecordNotFound() {
    7. return result
    8. }
    9. return c.NewScope(out).inlineCondition(where...).initialize().callCallbacks(c.parent.callbacks.creates).db
    10. } else if len(c.search.assignAttrs) > 0 {
    11. return c.NewScope(out).InstanceSet("gorm:update_interface", c.search.assignAttrs).callCallbacks(c.parent.callbacks.updates).db
    12. }
    13. return c
    14. }