You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
go-zero/tools/modelctl/model/modelgen/modeltemplate.go

248 lines
7.9 KiB
Go

package modelgen
import (
"bytes"
"errors"
"fmt"
"strings"
"text/template"
"zero/tools/modelctl/model"
"zero/tools/modelctl/util"
)
type (
Query struct {
Rows string
Args string
Values string
}
Update struct {
Rows string
Values string
}
Template struct {
Package string
PrimaryKeyField string
PrimaryKeyFieldCamel string
PrimaryKeyType string
ModelCamelWithLowerStart string
ModelLowerSplitByPound string
ModelCamelWithUpperStart string
Fields string
Abbr string
WithCache bool
Insert Query
// 包含where语句
Update Update
}
StructField struct {
// 字段名称,下划线
NameWithUnderline string
// 字段名称,驼峰式,大写开头
NameCamelWithUpperStart string
// 字段数据类型
DataType string
// 字段注释
Comment string
// 是否为主键
PrimaryKey bool
}
)
const (
fieldTemplateText = "{{.NameCamelWithUpperStart}} {{.DataType}} `db:\"{{.NameWithUnderline}}\" json:\"{{.NameWithUnderline}},omitempty\"` {{.Comment}}"
modelTemplateText = `package {{.Package}}
import (
"strings"
"time"
"zero/core/stores/redis"
"zero/core/stores/sqlx"
"zero/service/shared/builderx"
"zero/service/shared/cache"
)
var (
{{.ModelCamelWithLowerStart}}QueryRows = strings.Join(builderx.FieldNames(&{{.ModelCamelWithUpperStart}}{}), ",")
{{if .WithCache}}{{.ModelCamelWithLowerStart}}CachePrefix = "xjy#{{.ModelLowerSplitByPound}}#"
{{.ModelCamelWithLowerStart}}Expire = 7 * 24 * 3600{{end}}
)
type (
{{.ModelCamelWithUpperStart}}Model struct {
{{if .WithCache}} *CachedModel{{else}}
table string
conn sqlx.SqlConn{{end}}
}
{{.ModelCamelWithUpperStart}} struct {
{{.Fields}}
}
)
func New{{.ModelCamelWithUpperStart}}Model(table string, conn sqlx.SqlConn{{if .WithCache}}, rds *redis.Redis{{end}}) *{{.ModelCamelWithUpperStart}}Model {
{{if .WithCache}} return &{{.ModelCamelWithUpperStart}}Model{NewCachedModel(conn, table, rds)}
{{else}}return &{{.ModelCamelWithUpperStart}}Model{table:table,conn:conn}{{end}}
}
func ({{.Abbr}} *{{.ModelCamelWithUpperStart}}Model) Insert(data *{{.ModelCamelWithUpperStart}}) error {
querySql:="insert into "+{{.Abbr}}.table+" ({{.Insert.Rows}}) value ({{.Insert.Args}})"
_, err := {{.Abbr}}.conn.Exec(querySql, {{.Insert.Values}})
return err
}
func ({{.Abbr}} *{{.ModelCamelWithUpperStart}}Model) Update(data *{{.ModelCamelWithUpperStart}}) error {
{{if .WithCache}}err := {{.Abbr}}.cleanCache(data.{{.PrimaryKeyField}})
if err != nil {
return err
}
querySql := "update " + {{.Abbr}}.table + " set {{.Update.Rows}}"
_, err = {{.Abbr}}.conn.Exec(querySql,{{.Update.Values}} )
return err
{{else}}querySql := "update " + {{.Abbr}}.table + " set {{.Update.Rows}}"
_, err := {{.Abbr}}.conn.Exec(querySql,{{.Update.Values}} )
return err{{end}}
}
func ({{.Abbr}} *{{.ModelCamelWithUpperStart}}Model) FindOne({{.PrimaryKeyFieldCamel}} {{.PrimaryKeyType}})(*{{.ModelCamelWithUpperStart}},error){
querySql:="select "+{{.ModelCamelWithLowerStart}}QueryRows+" from "+{{.Abbr}}.table+" where {{.PrimaryKeyFieldCamel}} = ? limit 1"
var resp {{.ModelCamelWithUpperStart}}
{{if .WithCache}}key := cache.FormatKey({{.ModelCamelWithLowerStart}}CachePrefix,{{.PrimaryKeyFieldCamel}})
err := {{.Abbr}}.QueryRow(&resp, key, {{.ModelCamelWithLowerStart}}Expire, func(conn sqlx.Session, v interface{}) error {
return conn.QueryRow(v, querySql, {{.PrimaryKeyFieldCamel}})
})
if err != nil {
if err == sqlx.ErrNotFound {
return nil, ErrNotFound
}
return nil, err
}
{{else}}err := {{.Abbr}}.conn.QueryRow(&resp, querySql, {{.PrimaryKeyFieldCamel}})
if err != nil {
if err == sqlx.ErrNotFound {
return nil, ErrNotFound
}
return nil, err
}{{end}}
return &resp, nil
}
func ({{.Abbr}} *{{.ModelCamelWithUpperStart}}Model) DeleteById({{.PrimaryKeyFieldCamel}} {{.PrimaryKeyType}}) error {
{{if .WithCache}}err := {{.Abbr}}.cleanCache({{.PrimaryKeyFieldCamel}})
if err != nil {
return err
}
querySql := "delete from " + {{.Abbr}}.table + " where {{.PrimaryKeyFieldCamel}} = ? "
_, err = {{.Abbr}}.conn.Exec(querySql, {{.PrimaryKeyFieldCamel}})
return err
{{else}}querySql := "delete from " + {{.Abbr}}.table + " where {{.PrimaryKeyFieldCamel}} = ? "
_, err := {{.Abbr}}.conn.Exec(querySql, {{.PrimaryKeyFieldCamel}})
return err{{end}}
}
{{if .WithCache}}
func ({{.Abbr}} *{{.ModelCamelWithUpperStart}}Model) cleanCache({{.PrimaryKeyFieldCamel}} {{.PrimaryKeyType}}) error {
key := cache.FormatKey({{.ModelCamelWithLowerStart}}CachePrefix,{{.PrimaryKeyFieldCamel}})
_, err := {{.Abbr}}.rds.Del(key)
return err
}
{{end}}
`
)
func generateModelTemplate(packageName, table string, fileds []*Field) (*Template, error) {
list := make([]*StructField, 0)
var containsPrimaryKey bool
for _, item := range fileds {
goType, ok := model.CommonMysqlDataTypeMap[item.Type]
if !ok {
return nil, errors.New(fmt.Sprintf("table:%v,the data type %v of mysql does not match", table, item.Type))
}
if !containsPrimaryKey {
containsPrimaryKey = item.Primary == "PRI"
}
list = append(list, &StructField{
NameWithUnderline: item.Name,
NameCamelWithUpperStart: util.FmtUnderLine2Camel(item.Name, true),
DataType: goType,
Comment: item.Comment,
PrimaryKey: item.Primary == "PRI",
})
}
if !containsPrimaryKey {
return nil, errors.New(fmt.Sprintf("table:%v,primary key does not exist", table))
}
var structBuffer, insertRowsBuffer, insertArgBuffer, insertValuesBuffer, updateRowsBuffer, updateValuesBuffer bytes.Buffer
var primaryField *StructField
for index, item := range list {
out, err := convertField(item)
if err != nil {
return nil, err
}
structBuffer.WriteString(out + "\n")
if !item.PrimaryKey {
insertRowsBuffer.WriteString(item.NameWithUnderline)
insertArgBuffer.WriteString("?")
insertValuesBuffer.WriteString("data." + item.NameCamelWithUpperStart)
updateRowsBuffer.WriteString(item.NameWithUnderline + "=?")
updateValuesBuffer.WriteString("data." + item.NameCamelWithUpperStart)
if index < len(list)-1 {
insertRowsBuffer.WriteString(",")
insertArgBuffer.WriteString(",")
insertValuesBuffer.WriteString(",")
updateRowsBuffer.WriteString(",")
}
updateValuesBuffer.WriteString(",")
} else {
primaryField = item
}
}
updateRowsBuffer.WriteString(" where " + primaryField.NameWithUnderline + "=?")
updateValuesBuffer.WriteString(" data." + primaryField.NameCamelWithUpperStart)
modelSplitByPoundArr := strings.Replace(table, "_", "#", -1)
templateStruct := Template{
Package: packageName,
PrimaryKeyField: primaryField.NameCamelWithUpperStart,
PrimaryKeyFieldCamel: primaryField.NameWithUnderline,
PrimaryKeyType: primaryField.DataType,
ModelCamelWithLowerStart: util.FmtUnderLine2Camel(table, false),
ModelLowerSplitByPound: modelSplitByPoundArr,
ModelCamelWithUpperStart: util.FmtUnderLine2Camel(table, true),
Fields: structBuffer.String(),
Abbr: util.Abbr(table) + "m",
Insert: Query{
Rows: insertRowsBuffer.String(),
Args: insertArgBuffer.String(),
Values: insertValuesBuffer.String(),
},
Update: Update{
Rows: updateRowsBuffer.String(),
Values: updateValuesBuffer.String(),
},
}
return &templateStruct, nil
}
func convertField(field *StructField) (string, error) {
if strings.TrimSpace(field.Comment) != "" {
field.Comment = "// " + field.Comment
}
tl, err := template.New("").Parse(fieldTemplateText)
if err != nil {
return "", err
}
buf := bytes.NewBufferString("")
err = tl.Execute(buf, field)
if err != nil {
return "", err
}
return buf.String(), nil
}