本文主要研究一下gorm的CreateInBatchesgit
gorm.io/gorm@v1.20.11/finisher_api.gogithub
// CreateInBatches insert the value in batches into database func (db *DB) CreateInBatches(value interface{}, batchSize int) (tx *DB) { reflectValue := reflect.Indirect(reflect.ValueOf(value)) switch reflectValue.Kind() { case reflect.Slice, reflect.Array: var rowsAffected int64 tx = db.getInstance() tx.AddError(tx.Transaction(func(tx *DB) error { for i := 0; i < reflectValue.Len(); i += batchSize { ends := i + batchSize if ends > reflectValue.Len() { ends = reflectValue.Len() } subtx := tx.getInstance() subtx.Statement.Dest = reflectValue.Slice(i, ends).Interface() subtx.callbacks.Create().Execute(subtx) if subtx.Error != nil { return subtx.Error } rowsAffected += subtx.RowsAffected } return nil })) tx.RowsAffected = rowsAffected default: tx = db.getInstance() tx.Statement.Dest = value tx.callbacks.Create().Execute(tx) } return }
CreateInBatches會根據batchSize來分配進行create,可是他們是在同一個事務的,其rowsAffected是每一個批次的rowsAffected的累加
gorm.io/gorm@v1.20.11/gorm.gojson
// AddError add error to db func (db *DB) AddError(err error) error { if db.Error == nil { db.Error = err } else if err != nil { db.Error = fmt.Errorf("%v; %w", db.Error, err) } return db.Error }
tx.AddError方法在db.Error爲nil時直接更新爲err;不爲nil時判斷err是否爲nil,不爲nil時才更新爲err
gorm.io/gorm@v1.20.11/callbacks/transaction.goapi
func CommitOrRollbackTransaction(db *gorm.DB) { if !db.Config.SkipDefaultTransaction { if _, ok := db.InstanceGet("gorm:started_transaction"); ok { if db.Error == nil { db.Commit() } else { db.Rollback() } db.Statement.ConnPool = db.ConnPool } } }
CommitOrRollbackTransaction方法會判斷db.Error,若是不爲nil則執行db.Rollback()
func createInBatchesDemo(db *gorm.DB) { entities := []DemoEntity{ { Name: "coco", }, { Name: "bear", }, } result := db.Debug().CreateInBatches(&entities, 1) b, _ := json.Marshal(entities) log.Println("data:", string(b)) log.Println("result.RowsAffected:", result.RowsAffected, "result.Error:", result.Error) }
輸出code
2021/01/16 22:28:55 /demo.go:71 [0.384ms] [rows:1] INSERT INTO `demo_entities` (`created_at`,`updated_at`,`deleted_at`,`name`) VALUES ("2021-01-16 22:28:55.774","2021-01-16 22:28:55.774",NULL,"coco") 2021/01/16 22:28:55 /demo.go:71 [0.055ms] [rows:1] INSERT INTO `demo_entities` (`created_at`,`updated_at`,`deleted_at`,`name`) VALUES ("2021-01-16 22:28:55.774","2021-01-16 22:28:55.774",NULL,"bear") 2021/01/16 22:28:55 data: [{"ID":7,"CreatedAt":"2021-01-16T22:28:55.7743+08:00","UpdatedAt":"2021-01-16T22:28:55.7743+08:00","DeletedAt":null,"Name":"coco"},{"ID":8,"CreatedAt":"2021-01-16T22:28:55.774794+08:00","UpdatedAt":"2021-01-16T22:28:55.774794+08:00","DeletedAt":null,"Name":"bear"}] 2021/01/16 22:28:55 result.RowsAffected: 2 result.Error: <nil>
gorm的CreateInBatches容許用戶自定義batchSize,它會根據batchSize來分配進行create,可是他們是在同一個事務的,其rowsAffected是每一個批次的rowsAffected的累加。orm