gen_service.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. package services
  2. import (
  3. "flag"
  4. "fmt"
  5. "github.com/pkg/errors"
  6. "gorm.io/driver/mysql"
  7. "gorm.io/gen"
  8. "gorm.io/gorm"
  9. "gorm.io/gorm/logger"
  10. "jollia.cn/jolib/jokode"
  11. "jollia.cn/jolib/jokode/log"
  12. "strings"
  13. )
  14. const (
  15. defCfgFilePath = "conf/db.yaml"
  16. )
  17. type GenService struct {
  18. dbInstance *gorm.DB
  19. tables []string
  20. }
  21. func (s *GenService) Init() error {
  22. log.Warn("Enter: GenService.Init")
  23. defer log.Warn("Leave: GenService.Init")
  24. if !flag.Parsed() {
  25. flag.Parse()
  26. }
  27. if createCfgFileFlag {
  28. return nil
  29. }
  30. var (
  31. dbCfg *DbConfig
  32. cfgFilePath string
  33. force bool
  34. )
  35. if cfgFilePathFlag != "" {
  36. cfgFilePath = cfgFilePathFlag
  37. force = true
  38. } else {
  39. cfgFilePath = defCfgFilePath
  40. force = false
  41. }
  42. if cfg, err := loadConfigFromFile(cfgFilePath, force); err != nil {
  43. return errors.Wrapf(err, "try load db config from file '%s' fail", cfgFilePath)
  44. } else if cfg == nil {
  45. return errors.New("load db config returns nil")
  46. } else {
  47. dbCfg = cfg
  48. if len(cfg.Tables) > 0 {
  49. s.tables = cfg.Tables
  50. }
  51. }
  52. if !dbConfigFlag.IsZero() {
  53. if dbConfigFlag.Host != "" {
  54. dbCfg.Host = dbConfigFlag.Host
  55. }
  56. if dbConfigFlag.Port != 0 {
  57. dbCfg.Port = dbConfigFlag.Port
  58. }
  59. if dbConfigFlag.Schema != "" {
  60. dbCfg.Schema = dbConfigFlag.Schema
  61. }
  62. if dbConfigFlag.User != "" {
  63. dbCfg.User = dbConfigFlag.User
  64. }
  65. if dbConfigFlag.Pwd != "" {
  66. dbCfg.Pwd = dbConfigFlag.Pwd
  67. }
  68. }
  69. if err := s.initDatabase(dbCfg); err != nil {
  70. return errors.Wrap(err, "try init database fail")
  71. }
  72. return nil
  73. }
  74. func (s *GenService) initDatabase(dbCfg *DbConfig) error {
  75. if dbCfg == nil {
  76. return errors.New("can not init database with nil db config")
  77. }
  78. if err := dbCfg.FixDefaultValues(); err != nil {
  79. return errors.Wrap(err, "try fix default values of database config fail")
  80. }
  81. dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
  82. dbCfg.User,
  83. dbCfg.Pwd,
  84. dbCfg.Host,
  85. dbCfg.Port,
  86. dbCfg.Schema)
  87. if db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
  88. Logger: logger.Default.LogMode(logger.Info),
  89. }); err != nil {
  90. return errors.Wrapf(err, "try open database with dsn '%s' fail", dsn)
  91. } else {
  92. s.dbInstance = db
  93. }
  94. return nil
  95. }
  96. func loadConfigFromFile(filePath string, force bool) (*DbConfig, error) {
  97. cfg := &DbConfig{}
  98. if err := jokode.LoadConfigFromFile(cfg, filePath); err != nil {
  99. if force {
  100. return nil, errors.Wrapf(err, "try load config from file '%s' fail", filePath)
  101. }
  102. }
  103. return cfg, nil
  104. }
  105. func (s *GenService) Start() error {
  106. log.Warn("Enter: GenService.Start")
  107. defer log.Warn("Leave: GenService.Start")
  108. if createCfgFileFlag {
  109. cfgFilePath := cfgFilePathFlag
  110. if cfgFilePath == "" {
  111. cfgFilePath = defCfgFilePath
  112. }
  113. if jokode.FileExists(cfgFilePath) {
  114. return errors.Errorf("try create default config file '%s', but the file exists already", cfgFilePath)
  115. }
  116. cfg := &DbConfig{
  117. Host: "localhost",
  118. Port: 3306,
  119. User: "root",
  120. Pwd: "123456",
  121. Schema: "db",
  122. Tables: []string{"users", "roles"},
  123. }
  124. return errors.Wrapf(jokode.SaveConfigToFile(cfg, cfgFilePath), "try create default config file '%s' fail", cfgFilePath)
  125. }
  126. if s.dbInstance == nil {
  127. return errors.New("try start gen service with nil database instance")
  128. }
  129. g := gen.NewGenerator(gen.Config{
  130. OutPath: "model",
  131. WithUnitTest: false,
  132. FieldNullable: true,
  133. FieldCoverable: true,
  134. FieldSignable: true,
  135. FieldWithIndexTag: true,
  136. FieldWithTypeTag: true,
  137. Mode: gen.WithDefaultQuery | gen.WithQueryInterface,
  138. })
  139. g.WithDataTypeMap(map[string]func(columnType gorm.ColumnType) (dataType string){
  140. "tinyint": func(filedType gorm.ColumnType) string {
  141. if ct, ok := filedType.ColumnType(); ok {
  142. if strings.HasPrefix(strings.ToLower(ct), "tinyint(1)") {
  143. return "int8"
  144. }
  145. return "int16"
  146. } else {
  147. return "int32"
  148. }
  149. },
  150. })
  151. g.UseDB(s.dbInstance)
  152. if len(s.tables) > 0 {
  153. for _, tableName := range s.tables {
  154. g.GenerateModel(tableName)
  155. }
  156. } else {
  157. g.GenerateAllTable()
  158. }
  159. g.Execute()
  160. return nil
  161. }
  162. func (s *GenService) Stop() {
  163. // do nothing
  164. }
  165. func (s *GenService) GetName() string {
  166. return "GenService"
  167. }
  168. func (s *GenService) GetInitOrder() int {
  169. return 0
  170. }