sql_mapping.go 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. package tag
  2. import (
  3. "errors"
  4. "git.sxidc.com/go-tools/utils/reflectutils"
  5. "git.sxidc.com/go-tools/utils/strutils"
  6. "git.sxidc.com/service-supports/fserr"
  7. "github.com/iancoleman/strcase"
  8. "reflect"
  9. "strings"
  10. )
  11. type OnSqlMappingParsedFieldTagFunc func(fieldName string, entityFieldElemValue reflect.Value, sqlMapping *SqlMappingTag) error
  12. func UseSqlMappingTag(e any, onParsedFieldTagFunc OnSqlMappingParsedFieldTagFunc) error {
  13. if e == nil {
  14. return nil
  15. }
  16. entityValue := reflect.ValueOf(e)
  17. // 类型校验
  18. if !reflectutils.IsValueStructOrStructPointer(entityValue) {
  19. return fserr.New("参数不是结构或结构指针")
  20. }
  21. entityElemValue := reflectutils.PointerValueElem(entityValue)
  22. err := parseEntitySqlMappingTag(entityElemValue, onParsedFieldTagFunc)
  23. if err != nil {
  24. return err
  25. }
  26. return nil
  27. }
  28. func parseEntitySqlMappingTag(entityElemValue reflect.Value, onParsedFieldTagFunc OnSqlMappingParsedFieldTagFunc) error {
  29. for i := 0; i < entityElemValue.NumField(); i++ {
  30. entityField := entityElemValue.Type().Field(i)
  31. entityFieldValue := entityElemValue.Field(i)
  32. // 无效值,不进行映射
  33. if !entityFieldValue.IsValid() {
  34. continue
  35. }
  36. if entityFieldValue.Kind() == reflect.Pointer && entityFieldValue.IsNil() {
  37. entityFieldValue.Set(reflect.New(entityField.Type.Elem()))
  38. }
  39. entityFieldElemValue := reflectutils.PointerValueElem(entityFieldValue)
  40. tagStr := entityField.Tag.Get(sqlMappingTagKey)
  41. sqlMapping, err := parseSqlMappingTag(entityField, tagStr)
  42. if err != nil {
  43. return err
  44. }
  45. if sqlMapping == nil {
  46. continue
  47. }
  48. // 结构类型的字段,解析结构内部
  49. if entityFieldElemValue.Kind() == reflect.Struct &&
  50. !reflectutils.IsValueTime(entityFieldElemValue) {
  51. err := parseEntitySqlMappingTag(entityFieldElemValue, onParsedFieldTagFunc)
  52. if err != nil {
  53. return err
  54. }
  55. continue
  56. }
  57. err = onParsedFieldTagFunc(entityField.Name, entityFieldElemValue, sqlMapping)
  58. if err != nil {
  59. return err
  60. }
  61. }
  62. return nil
  63. }
  64. const (
  65. sqlMappingDefaultKeyColumnName = "id"
  66. sqlMappingDefaultJoinWith = "::"
  67. sqlMappingTagPartSeparator = ";"
  68. sqlMappingTagPartKeyValueSeparator = ":"
  69. )
  70. const (
  71. sqlMappingTagKey = "sqlmapping"
  72. sqlMappingIgnore = "-"
  73. sqlMappingColumn = "column"
  74. sqlMappingKey = "key"
  75. sqlMappingNotUpdate = "notUpdate"
  76. sqlMappingUpdateClear = "updateClear"
  77. sqlMappingAes = "aes"
  78. sqlMappingJoinWith = "joinWith"
  79. sqlMappingTrim = "trim"
  80. sqlMappingTrimPrefix = "trimPrefix"
  81. sqlMappingTrimSuffix = "trimSuffix"
  82. )
  83. type SqlMappingTag struct {
  84. Name string
  85. IsKey bool
  86. CanUpdate bool
  87. CanUpdateClear bool
  88. AESKey string
  89. JoinWith string
  90. Trim string
  91. TrimPrefix string
  92. TrimSuffix string
  93. }
  94. func parseSqlMappingTag(field reflect.StructField, tagStr string) (*SqlMappingTag, error) {
  95. if tagStr == sqlMappingIgnore {
  96. return nil, nil
  97. }
  98. sqlMappingTag := &SqlMappingTag{
  99. Name: strcase.ToSnake(field.Name),
  100. IsKey: false,
  101. CanUpdate: true,
  102. CanUpdateClear: false,
  103. AESKey: "",
  104. JoinWith: sqlMappingDefaultJoinWith,
  105. Trim: "",
  106. TrimPrefix: "",
  107. TrimSuffix: "",
  108. }
  109. if sqlMappingTag.Name == sqlMappingDefaultKeyColumnName {
  110. sqlMappingTag.IsKey = true
  111. sqlMappingTag.CanUpdate = false
  112. }
  113. if strutils.IsStringEmpty(tagStr) {
  114. return sqlMappingTag, nil
  115. }
  116. sqlMappingParts := strings.Split(tagStr, sqlMappingTagPartSeparator)
  117. if sqlMappingParts != nil || len(sqlMappingParts) != 0 {
  118. for _, sqlMappingPart := range sqlMappingParts {
  119. sqlMappingPartKeyValue := strings.SplitN(strings.TrimSpace(sqlMappingPart), sqlMappingTagPartKeyValueSeparator, 2)
  120. if sqlMappingPartKeyValue != nil && len(sqlMappingPartKeyValue) == 2 && strutils.IsStringNotEmpty(sqlMappingPartKeyValue[1]) {
  121. sqlMappingPartKeyValue[1] = strings.Trim(sqlMappingPartKeyValue[1], "'")
  122. }
  123. switch sqlMappingPartKeyValue[0] {
  124. case sqlMappingColumn:
  125. if strutils.IsStringEmpty(sqlMappingPartKeyValue[1]) {
  126. return nil, errors.New("column没有赋值列名")
  127. }
  128. sqlMappingTag.Name = sqlMappingPartKeyValue[1]
  129. case sqlMappingKey:
  130. sqlMappingTag.IsKey = true
  131. sqlMappingTag.CanUpdate = false
  132. case sqlMappingNotUpdate:
  133. sqlMappingTag.CanUpdate = false
  134. sqlMappingTag.CanUpdateClear = false
  135. case sqlMappingUpdateClear:
  136. if !sqlMappingTag.CanUpdate {
  137. sqlMappingTag.CanUpdateClear = false
  138. } else {
  139. sqlMappingTag.CanUpdateClear = true
  140. }
  141. case sqlMappingAes:
  142. if len(sqlMappingPartKeyValue[1]) != 32 {
  143. return nil, errors.New("AES密钥长度应该为32个字节")
  144. }
  145. sqlMappingTag.AESKey = sqlMappingPartKeyValue[1]
  146. case sqlMappingJoinWith:
  147. if strutils.IsStringEmpty(sqlMappingPartKeyValue[1]) {
  148. return nil, errors.New(sqlMappingJoinWith + "没有赋值分隔符")
  149. }
  150. sqlMappingTag.JoinWith = sqlMappingPartKeyValue[1]
  151. case sqlMappingTrim:
  152. sqlMappingTag.Trim = sqlMappingPartKeyValue[1]
  153. case sqlMappingTrimPrefix:
  154. sqlMappingTag.TrimPrefix = sqlMappingPartKeyValue[1]
  155. case sqlMappingTrimSuffix:
  156. sqlMappingTag.TrimSuffix = sqlMappingPartKeyValue[1]
  157. default:
  158. continue
  159. }
  160. }
  161. }
  162. return sqlMappingTag, nil
  163. }