golang xorm mysql代码生成器


本文摘自网络,作者,侵删。

原来的代码生成器都是用java写的,心血来潮,把其中的生产golang数据层的代码,用golang实现了一下。

主体代码

package main

import (
    "flag"
    "fmt"
    "os"
    "strings"
    "text/template"
    "unsafe"

    _ "github.com/go-sql-driver/mysql"
    "xorm.io/xorm"
)

const (
    selectCurrentDbSql = "SELECT DATABASE()"
    allColumnInfoSql   = "SELECT * FROM information_schema.columns WHERE table_schema =? ORDER BY table_schema ASC,table_name ASC,ordinal_position ASC"
)

func main() {
    db := flag.String("db", "", "database connection string")
    tplName := flag.String("tplname", "repository.tpl", "code template name")
    tpl := flag.String("tpl", "tpl/repository.tpl", "code template file")
    readonly := flag.Bool("readonly", false, "readonly")
    output := flag.String("output", "./repository", "output file path")

    flag.Parse()

    if db == nil || *db == "" {
        fmt.Println("database connection string can not be empty")

        return
    }

    engine, err := xorm.NewEngine("mysql", *db)

    if err != nil {
        fmt.Println("can not create database engine,err:", err)

        return
    }

    currentDb := ""

    if _, err := engine.SQL(selectCurrentDbSql).Get(&currentDb); err != nil {
        fmt.Println("can not get current database,err:", err)

        return
    }

    columns := make([]DataColumn, 0)

    if err := engine.SQL(allColumnInfoSql, currentDb).Find(&columns); err != nil {
        fmt.Println("can not get column information,err:", err)

        return
    }

    tableMap := make(map[string][]DataColumn)

    for _, column := range columns {
        tableName := column.TableName

        if _, ok := tableMap[tableName]; !ok {
            tableMap[tableName] = make([]DataColumn, 0)
        }

        tableMap[tableName] = append(tableMap[tableName], column)
    }

    funcMap := template.FuncMap{"upperCamelCase": UpperCamelCase, "lowerCamelCase": LowerCamelCase}

    t, err := template.New(*tplName).Funcs(funcMap).ParseFiles(*tpl)

    if err != nil {
        fmt.Println("parse file err:", err)
        return
    }

    os.RemoveAll(*output)

    for table, columns := range tableMap {
        if _, err := os.Stat(*output); os.IsNotExist(err) {
            os.Mkdir(*output, 0777)
            os.Chmod(*output, 0777)
        }

        f, err := os.OpenFile(*output+"/"+table+"_repository.go", os.O_CREATE|os.O_WRONLY, 0666)

        defer f.Close()

        if err != nil {
            fmt.Println("can not create output file,err:", err)

            return
        }

        if err := t.Execute(f, Config{TableName: table, Readonly: *readonly, Columns: columns}); err != nil {
            fmt.Println("There was an error:", err.Error())
        }
    }

}

type Config struct {
    TableName string
    Readonly  bool
    Columns   []DataColumn
}

type DataColumn struct {
    TableSchema            string
    TableName              string
    ColumnName             string
    OrdinalPosition        int
    ColumnDefault          string
    IsNullable             string
    DataType               string
    CharacterMaximumLength string
    CharacterOctetLength   string
    NumericPrecision       string
    NumbericScale          string
    DatetimePrecision      string
    ColumnType             string
    ColumnKey              string
    Extra                  string
    ColumnComment          string
}

func (c *DataColumn) GoLangType() string {
    dataType := strings.ToLower(c.DataType)
    nullable := strings.ToLower(c.IsNullable) == "yes"

    if dataType == "int" {
        if nullable {
            return "*int"
        }

        return "int"
    }

    if dataType == "varchar" || dataType == "text" || dataType == "longtext" {
        if nullable {
            return "*string"
        }

        return "string"
    }

    if dataType == "long" || dataType == "bigint" {
        if nullable {
            return "*int64"
        }

        return "int64"
    }

    if dataType == "decimal" {
        if nullable {
            return "*float64"
        }

        return "ifloat64"
    }

    if dataType == "datetime" {
        if nullable {
            return "*time.Time"
        }

        return "time.Time"
    }

    return dataType
}

func (c *DataColumn) Tag() string {
    name := strings.ToLower(c.ColumnName)
    dataType := strings.ToLower(c.DataType)
    identity := strings.ToLower(c.Extra) == "auto_increment"
    primary := strings.ToLower(c.ColumnKey) == "PRI"
    nullable := strings.ToLower(c.IsNullable) == "yes"

    sb := new(strings.Builder)

    sb.WriteString("`xorm:\"")
    sb.WriteString(dataType)
    sb.WriteString(" '")
    sb.WriteString(name)
    sb.WriteString("'")

    if identity {
        sb.WriteString(" autoincr")
    }

    if primary {
        sb.WriteString(" pk")
    }

    if nullable {
        sb.WriteString(" null")
    } else {
        sb.WriteString(" notnull")
    }

    sb.WriteString(" default(")

    if dataType == "varchar" || dataType == "text" || dataType == "longtext" {
        sb.WriteString("'")
    }

    sb.WriteString(c.ColumnDefault)

    if dataType == "varchar" || dataType == "text" || dataType == "longtext" {
        sb.WriteString("'")
    }

    sb.WriteString(")")

    sb.WriteString(" comment('")
    sb.WriteString(c.ColumnComment)
    sb.WriteString("')")

    sb.WriteString("\" json:\"")

    if name == "del_status" {
        sb.WriteString("-")
    } else {
        sb.WriteString(LowerCamelCase(c.ColumnName))
    }

    sb.WriteString("\"`")

    return sb.String()
}

func UpperCamelCase(txt string) string {
    sb := new(strings.Builder)

    strs := strings.Split(txt, "_")

    for _, str := range strs {
        sb.WriteString(strings.ToUpper(string(str[0])))
        sb.WriteString(str[1:])
    }

    return sb.String()
}

func LowerCamelCase(txt string) string {
    sb := new(strings.Builder)

    strs := strings.Split(txt, "_")

    for _, str := range strs {
        sb.WriteString(strings.ToLower(string(str[0])))
        sb.WriteString(str[1:])
    }

    return sb.String()
}

func BytesToString(b []byte) string {
    return *(*string)(unsafe.Pointer(&b))
}

模板文件,tpl/repository.tpl

package repository

type {{upperCamelCase .TableName}} struct{
 {{ range $column := .Columns}}
 {{upperCamelCase .ColumnName }} {{.GoLangType}} {{.Tag}} 
 {{ end }}
}

{{if not .Readonly}}
var(
{{lowerCamelCase .TableName}}Columns=[]string{
         {{ range $column := .Columns}}
 "{{.ColumnName }}",
 {{ end }}
    }
    
{{lowerCamelCase .TableName}}ColumnMap=map[string]string{
         {{ range $column := .Columns}}
 "{{.ColumnName }}":"{{.ColumnName }}",
 {{ end }}
    }
)
{{end}}
type {{upperCamelCase .TableName}}Repository interface {
    {{if not .Readonly}}
    Create(entity {{upperCamelCase .TableName}}) ({{upperCamelCase .TableName}}, error)
    {{end}}
    {{if not .Readonly}}
    CreateBySession(session *xorm.Session, entity {{upperCamelCase .TableName}}) ({{upperCamelCase .TableName}}, error)
    {{end}}
    {{if not .Readonly}}
    DeleteById(id int64) (int64, error)
    {{end}}
    {{if not .Readonly}}
    DeleteBySessionAndId(session *xorm.Session, id int64) (int64, error)
    {{end}}
    {{if not .Readonly}}
    Update(entity {{upperCamelCase .TableName}}, columns []string) ({{upperCamelCase .TableName}}, error)
    {{end}}
    {{if not .Readonly}}
    UpdateBySession(session *xorm.Session, entity {{upperCamelCase .TableName}}, columns []string) ({{upperCamelCase .TableName}}, error)
    {{end}}
    FindById(id int64) ({{upperCamelCase .TableName}}, error)
    {{if not .Readonly}}
    FindBySessionAndId(session *xorm.Session, id int64) ({{upperCamelCase .TableName}}, error)
    {{end}}
}

type {{lowerCamelCase .TableName}}Repository  struct {
    engine *xorm.Engine
}

func New{{upperCamelCase .TableName}}Repository(engine *xorm.Engine) {{upperCamelCase .TableName}}Repository {
    return &{{lowerCamelCase .TableName}}Repository{
        engine: engine,
    }
}

{{if not .Readonly}}
func (r *{{lowerCamelCase .TableName}}Repository) Create(entity {{upperCamelCase .TableName}}) ({{upperCamelCase .TableName}}, error) {
    _, err := r.engine.Insert(&entity)

    return entity, err
}
{{end}}

{{if not .Readonly}}
func (r *{{lowerCamelCase .TableName}}Repository) CreateBySession(session *xorm.Session, entity {{upperCamelCase .TableName}}) ({{upperCamelCase .TableName}}, error) {
    _, err := session.Insert(&entity)

    return entity, err
}
{{end}}

{{if not .Readonly}}
func (r *{{lowerCamelCase .TableName}}Repository) DeleteById(id int64) (int64, error) {
    return r.engine.ID(id).Cols("del_status", "update_time").Update(&{{upperCamelCase .TableName}}{DelStatus: 1, UpdateTime: time.Now()})
}
{{end}}

{{if not .Readonly}}
func (r *{{lowerCamelCase .TableName}}Repository) DeleteBySessionAndId(session *xorm.Session, id int64) (int64, error) {
    return session.ID(id).Cols("del_status", "update_time").Update(&{{upperCamelCase .TableName}}{DelStatus: 1, UpdateTime: time.Now()})
}
{{end}}

{{if not .Readonly}}
func (r *{{lowerCamelCase .TableName}}Repository) Update(entity {{upperCamelCase .TableName}},columns []string) ({{upperCamelCase .TableName}}, error) {
    _, err := r.engine.ID(entity.Id).Cols(columns...).Update(&entity)

    return entity, err
}
{{end}}

{{if not .Readonly}}
func (r *{{lowerCamelCase .TableName}}Repository) UpdateBySession(session *xorm.Session, entity {{upperCamelCase .TableName}},columns []string) ({{upperCamelCase .TableName}}, error) {
    _, err := session.ID(entity.Id).Cols(columns...).Update(&entity)

    return entity, err
}
{{end}}

func (r *{{lowerCamelCase .TableName}}Repository) FindById(id int64) ({{upperCamelCase .TableName}}, error) {
    entity := new({{upperCamelCase .TableName}})

    _, err := r.engine.ID(id).Where("del_status=0").Get(entity)

    return *entity, err
}

{{if not .Readonly}}
func (r *{{lowerCamelCase .TableName}}Repository) FindBySessionAndId(session *xorm.Session, id int64) ({{upperCamelCase .TableName}}, error) {
    entity := new({{upperCamelCase .TableName}})

    _, err := session.ID(id).Where("del_status=0").Get(entity)

    return *entity, err
}
{{end}}

本文来自:简书

感谢作者:EasyNetCN

查看原文:golang xorm mysql代码生成器

相关阅读 >>

Go 语言常用排序

Go link

Golang 入门系列(五)Go语言中的面向对象

[译]Go语言最佳实战[一]

Go的值类型和引用类型2——内存分配规则

阅读Golang 切片(slice)底层源码

解构 dubbo-Go 的核心注册引擎 nacos

手撸Golang 创建型设计模式 建造者模式

无缝连接 dubbo-Go 与 grpc

Golang 创建型设计模式 工厂方法

更多相关阅读请进入《Go》频道 >>




打赏

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码打赏,您说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

分享从这里开始,精彩与您同在

评论

管理员已关闭评论功能...