package sql_mapping import ( "git.sxidc.com/go-framework/baize/framework/core/infrastructure/logger" "git.sxidc.com/go-tools/utils/reflectutils" "git.sxidc.com/go-tools/utils/strutils" "git.sxidc.com/go-tools/utils/template" "github.com/iancoleman/strcase" "github.com/pkg/errors" "reflect" "strings" ) const ( defaultKeyColumnName = "id" defaultJoinWith = "::" tagPartSeparator = ";" tagPartKeyValueSeparator = ":" ) const ( tagKey = "sqlmapping" tagPartIgnore = "-" tagPartColumn = "column" tagPartKey = "key" tagPartNotUpdate = "notUpdate" tagPartUpdateClear = "updateClear" tagPartAes = "aes" tagPartJoinWith = "joinWith" tagPartTrim = "trim" tagPartTrimPrefix = "trimPrefix" tagPartTrimSuffix = "trimSuffix" ) type Tag struct { Name string IsKey bool CanUpdate bool CanUpdateClear bool JoinWith string AESKey string Trim string TrimPrefix string TrimSuffix string } func parseTag(entityElemValue reflect.Value, onParsedFieldTagFunc OnParsedFieldTagFunc) error { for i := 0; i < entityElemValue.NumField(); i++ { entityField := entityElemValue.Type().Field(i) entityFieldValue := entityElemValue.Field(i) // 无效值,不进行映射 if !entityFieldValue.IsValid() { continue } if entityFieldValue.Kind() == reflect.Pointer && entityFieldValue.IsNil() { if !entityFieldValue.CanSet() { return errors.New("无法设置值,请检查是否传递的是非指针结构变量且字段为nil") } entityFieldValue.Set(reflect.New(entityField.Type.Elem())) } entityFieldElemValue := reflectutils.PointerValueElem(entityFieldValue) tagStr := entityField.Tag.Get(tagKey) tag, err := parseFieldTag(entityField, tagStr) if err != nil { return err } if tag == nil { continue } // 结构类型的字段,解析结构内部 if entityFieldElemValue.Kind() == reflect.Struct && !reflectutils.IsValueTime(entityFieldElemValue) { err := parseTag(entityFieldElemValue, onParsedFieldTagFunc) if err != nil { return err } continue } err = onParsedFieldTagFunc(entityField.Name, entityFieldElemValue, tag) if err != nil { return err } } return nil } func parseFieldTag(field reflect.StructField, tagStr string) (*Tag, error) { if tagStr == tagPartIgnore { return nil, nil } tag := &Tag{ Name: strcase.ToSnake(template.Id(field.Name)), IsKey: false, CanUpdate: true, CanUpdateClear: false, JoinWith: defaultJoinWith, AESKey: "", Trim: "", TrimPrefix: "", TrimSuffix: "", } if tag.Name == defaultKeyColumnName { tag.IsKey = true tag.CanUpdate = false } if strutils.IsStringEmpty(tagStr) { return tag, nil } tagParts := strings.Split(tagStr, tagPartSeparator) if tagParts != nil || len(tagParts) != 0 { for _, tagPart := range tagParts { tagPartKeyValue := strings.SplitN(strings.TrimSpace(tagPart), tagPartKeyValueSeparator, 2) if tagPartKeyValue != nil && len(tagPartKeyValue) == 2 && strutils.IsStringNotEmpty(tagPartKeyValue[1]) { tagPartKeyValue[1] = strings.Trim(tagPartKeyValue[1], "'") } if strutils.IsStringEmpty(tagPartKeyValue[0]) { continue } switch tagPartKeyValue[0] { case tagPartColumn: if strutils.IsStringEmpty(tagPartKeyValue[1]) { return nil, errors.New("column没有赋值列名") } tag.Name = tagPartKeyValue[1] case tagPartKey: tag.IsKey = true tag.CanUpdate = false case tagPartNotUpdate: tag.CanUpdate = false tag.CanUpdateClear = false case tagPartUpdateClear: if !tag.CanUpdate { tag.CanUpdateClear = false } else { tag.CanUpdateClear = true } case tagPartAes: if len(tagPartKeyValue[1]) != 32 { return nil, errors.New("AES密钥长度应该为32个字节") } tag.AESKey = tagPartKeyValue[1] case tagPartJoinWith: if strutils.IsStringEmpty(tagPartKeyValue[1]) { return nil, errors.New(tagPartJoinWith + "没有赋值分隔符") } tag.JoinWith = tagPartKeyValue[1] case tagPartTrim: tag.Trim = tagPartKeyValue[1] case tagPartTrimPrefix: tag.TrimPrefix = tagPartKeyValue[1] case tagPartTrimSuffix: tag.TrimSuffix = tagPartKeyValue[1] default: err := errors.New(tagKey + "不支持的tag: " + tagPartKeyValue[0]) logger.GetInstance().Error(err) continue } } } return tag, nil }