package dao import ( "reflect" "time" "git.rosy.net.cn/baseapi/utils" "git.rosy.net.cn/jx-callback/business/model" "git.rosy.net.cn/jx-callback/globals" "git.rosy.net.cn/jx-callback/globals/refutil" ) type KVUpdateItem struct { Item interface{} KVs map[string]interface{} } // 这里面的函数要求实体是IDCUDL的,即含有ID, UpdatedAt, LastOperator, DeletedAt字段 func GetEntitiesByKV(db *DaoDB, item interface{}, conditions map[string]interface{}, isIncludeDeleted bool) (err error) { if db == nil { db = GetDB() } err = utils.CallFuncLogError(func() error { typeInfo := reflect.TypeOf(item).Elem().Elem() if typeInfo.Kind() == reflect.Ptr { typeInfo = typeInfo.Elem() } qs := db.Db.QueryTable(reflect.New(typeInfo).Interface()) for k, v := range conditions { qs = qs.Filter(k, v) } qs = qs.Limit(-1) if !isIncludeDeleted { if _, ok := typeInfo.FieldByName(model.FieldDeletedAt); ok { qs = qs.Filter(model.FieldDeletedAt, utils.DefaultTimeValue) } } _, err = qs.Limit(-1).All(item) return err }, reflect.TypeOf(item).Name()) return err } func UpdateEntityByKV(db *DaoDB, item interface{}, kvs map[string]interface{}, conditions map[string]interface{}) (num int64, err error) { if db == nil { db = GetDB() } qs := db.Db.QueryTable(item) if conditions == nil { qs = qs.Filter(model.FieldID, refutil.GetObjFieldByName(item, model.FieldID)) } else { for k, v := range conditions { qs = qs.Filter(k, v) } } num, err = qs.Update(kvs) if err != nil && !IsDuplicateError(err) { globals.SugarLogger.Errorf("UpdateEntityByKV %s failed with error:%v", reflect.TypeOf(item).Name(), err) } return num, err } func BatchUpdateEntityByKV(db *DaoDB, items []*KVUpdateItem) (num int64, err error) { if len(items) > 0 { // 不用事务应该是OK的吧,用事务经常会导致死锁(不同平台在同步同一条数据) // Begin(db) // defer func() { // if r := recover(); r != nil || err != nil { // Rollback(db) // if r != nil { // panic(r) // } // } // }() var item *KVUpdateItem defer func() { if r := recover(); r != nil { if item != nil { var bindID int64 value := refutil.CheckAndGetStructValue(item.Item).FieldByName(model.FieldID) if value.IsValid() { bindID = value.Int() } globals.SugarLogger.Debugf("BatchUpdateEntityByKV panic, bindID:%d, KVs:%s", bindID, utils.Format4Output(item.KVs, true)) } panic(r) } }() for _, item = range items { num2, err2 := UpdateEntityByKV(db, item.Item, item.KVs, nil) if err = err2; err != nil { return 0, err } num += num2 } // Commit(db) } return num, nil } func UpdateEntityLogically(db *DaoDB, item interface{}, kvs map[string]interface{}, userName string, conditions map[string]interface{}) (num int64, err error) { if conditions != nil && refutil.IsFieldExist(item, model.FieldDeletedAt) { conditions = utils.MergeMaps(conditions, map[string]interface{}{ model.FieldDeletedAt: utils.DefaultTimeValue, }) } params := map[string]interface{}{ model.FieldUpdatedAt: time.Now(), } if userName != "" { params[model.FieldLastOperator] = userName } return UpdateEntityByKV(db, item, utils.MergeMaps(kvs, params), conditions) } // 此函数会更新同步标志 func UpdateEntityLogicallyAndUpdateSyncStatus(db *DaoDB, item interface{}, kvs map[string]interface{}, userName string, conditions map[string]interface{}, syncStatusFieldName string, valueMask int) (num int64, err error) { if conditions != nil && refutil.IsFieldExist(item, model.FieldDeletedAt) { conditions = utils.MergeMaps(conditions, map[string]interface{}{ model.FieldDeletedAt: utils.DefaultTimeValue, }) } else { conditions = map[string]interface{}{ model.FieldID: refutil.GetObjFieldByName(item, model.FieldID), } } typeInfo := reflect.TypeOf(item) valueRows := reflect.New(reflect.SliceOf(typeInfo)) rows := valueRows.Interface() if err = GetEntitiesByKV(db, rows, conditions, false); err == nil { // globals.SugarLogger.Debug(utils.Format4Output(rows, false)) valueRows = reflect.Indirect(valueRows) for i := 0; i < valueRows.Len(); i++ { value := reflect.Indirect(valueRows.Index(i)) status := value.FieldByName(syncStatusFieldName).Int() | int64(valueMask) params := map[string]interface{}{ model.FieldUpdatedAt: time.Now(), syncStatusFieldName: status, } if userName != "" { params[model.FieldLastOperator] = userName } num2, err2 := UpdateEntityByKV(db, value.Interface(), utils.MergeMaps(kvs, params), nil) if err = err2; err == nil { num += num2 } else { return num, err } } } return num, err } func DeleteEntityLogically(db *DaoDB, item interface{}, kvs map[string]interface{}, userName string, conditions map[string]interface{}) (num int64, err error) { return UpdateEntityLogically(db, item, utils.MergeMaps(kvs, map[string]interface{}{ model.FieldDeletedAt: time.Now(), }), userName, conditions) }