feat(gendao): 添加代码生成工具用于自动生成DAO层代码
- 实现了完整的gendao命令行工具功能 - 添加了模板文件用于生成DAO、DO、Entity等代码结构 - 集成了数据库表字段映射和类型转换功能 - 支持分片表模式匹配和自定义配置选项 - 实现了代码清理和格式化功能 - 提供了灵活的表名过滤和前缀处理机制
This commit is contained in:
@@ -28,8 +28,8 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/utils"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/utils"
|
||||
)
|
||||
|
||||
type (
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
)
|
||||
|
||||
func doClear(items *CGenDaoInternalGenItems) {
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/consts"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/database"
|
||||
@@ -21,9 +22,8 @@ import (
|
||||
"github.com/gogf/gf/v2/os/gview"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/consts"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/utils"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/utils"
|
||||
)
|
||||
|
||||
func generateDao(ctx context.Context, in CGenDaoInternalInput) {
|
||||
@@ -12,14 +12,14 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/consts"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gview"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/consts"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/utils"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/utils"
|
||||
)
|
||||
|
||||
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
@@ -11,13 +11,13 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/consts"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gview"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/consts"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/utils"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/utils"
|
||||
)
|
||||
|
||||
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
||||
@@ -14,15 +14,15 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/consts"
|
||||
"git.magicany.cc/black1552/gin-base/database"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gview"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/consts"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/utils"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/utils"
|
||||
)
|
||||
|
||||
// generateTable generates dao files for given tables.
|
||||
+2
-2
@@ -17,8 +17,8 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/consts"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/consts"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// GoFmt formats the source file and adds or removes import statements as necessary.
|
||||
+1
-1
@@ -16,7 +16,7 @@ import (
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/mlog"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/mlog"
|
||||
)
|
||||
|
||||
// HTTPDownloadFileWithPercent downloads target url file to local path with percent process printing.
|
||||
+1
-1
@@ -12,7 +12,7 @@ import (
|
||||
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gf-source/internal/utility/utils"
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao/internal/utility/utils"
|
||||
)
|
||||
|
||||
func Test_GetModPath(t *testing.T) {
|
||||
@@ -1,12 +0,0 @@
|
||||
module git.magicany.cc/black1552/gin-base/cmd/gf-source
|
||||
|
||||
go 1.25.0
|
||||
|
||||
require (
|
||||
git.magicany.cc/black1552/gin-base v0.0.0
|
||||
github.com/gogf/gf/v2 v2.10.0
|
||||
github.com/olekukonko/tablewriter v1.1.4
|
||||
golang.org/x/mod v0.33.0
|
||||
)
|
||||
|
||||
replace git.magicany.cc/black1552/gin-base => ../..
|
||||
@@ -1,87 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenCtrlControllerEmpty = `
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package {Module}
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerNewEmpty = `
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package {Module}
|
||||
|
||||
import (
|
||||
{ImportPath}
|
||||
)
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerNewFunc = `
|
||||
type {CtrlName} struct{}
|
||||
|
||||
func {NewFuncName}() {InterfaceName} {
|
||||
return &{CtrlName}{}
|
||||
}
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerMethodFunc = `
|
||||
package {Module}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"{ImportPath}"
|
||||
)
|
||||
{MethodComment}
|
||||
func (c *{CtrlName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerHeader = `
|
||||
package {Module}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"{ImportPath}"
|
||||
)
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerMethodFuncMerge = `
|
||||
{MethodComment}
|
||||
func (c *{CtrlName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
||||
`
|
||||
|
||||
const TemplateGenCtrlApiInterface = `
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package {Module}
|
||||
|
||||
import (
|
||||
{ImportPaths}
|
||||
)
|
||||
|
||||
{Interfaces}
|
||||
`
|
||||
@@ -1,89 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenCtrlSdkPkgNew = `
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package {PkgName}
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/gogf/gf/contrib/sdk/httpclient/v2"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
)
|
||||
|
||||
type implementer struct {
|
||||
config httpclient.Config
|
||||
}
|
||||
|
||||
func New(config httpclient.Config) IClient {
|
||||
return &implementer{
|
||||
config: config,
|
||||
}
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlSdkIClient = `
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package {PkgName}
|
||||
|
||||
import (
|
||||
)
|
||||
|
||||
type IClient interface {
|
||||
}
|
||||
`
|
||||
|
||||
const TemplateGenCtrlSdkImplementer = `
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package {PkgName}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/contrib/sdk/httpclient/v2"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
{ImportPaths}
|
||||
)
|
||||
|
||||
type implementer{ImplementerName} struct {
|
||||
*httpclient.Client
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlSdkImplementerNew = `
|
||||
func (i *implementer) {ImplementerName}() {Module}.I{ImplementerName} {
|
||||
var (
|
||||
client = httpclient.New(i.config)
|
||||
prefix = gstr.TrimRight(i.config.URL, "/") + "{VersionPrefix}"
|
||||
)
|
||||
client.Client = client.Prefix(prefix)
|
||||
return &implementer{ImplementerName}{client}
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlSdkImplementerFunc = `{MethodComment}
|
||||
func (i *implementer{ImplementerName}) {MethodName}(ctx context.Context, req *{Version}.{MethodName}Req) (res *{Version}.{MethodName}Res, err error) {
|
||||
err = i.Request(ctx, req, &res)
|
||||
return
|
||||
}
|
||||
`
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenEnums = `
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ================================================================================
|
||||
|
||||
package {PackageName}
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/util/gtag"
|
||||
)
|
||||
|
||||
func init() {
|
||||
gtag.SetGlobalEnums({EnumsJson})
|
||||
}
|
||||
`
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplatePbEntityMessageContent = `
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
syntax = "proto3";
|
||||
|
||||
package {PackageName};
|
||||
|
||||
option go_package = "{GoPackage}";
|
||||
{OptionContent}
|
||||
{Imports}
|
||||
|
||||
{EntityMessage}
|
||||
`
|
||||
@@ -1,41 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenServiceContentHead = `
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package {PackageName}
|
||||
|
||||
{Imports}
|
||||
`
|
||||
|
||||
const TemplateGenServiceContentInterface = `
|
||||
{InterfaceName} interface {
|
||||
{FuncDefinition}
|
||||
}
|
||||
`
|
||||
|
||||
const TemplateGenServiceContentVariable = `
|
||||
local{StructName} {InterfaceName}
|
||||
`
|
||||
|
||||
const TemplateGenServiceContentRegister = `
|
||||
func {StructName}() {InterfaceName} {
|
||||
if local{StructName} == nil {
|
||||
panic("implement not found for interface {InterfaceName}, forgot register?")
|
||||
}
|
||||
return local{StructName}
|
||||
}
|
||||
|
||||
func Register{StructName}(i {InterfaceName}) {
|
||||
local{StructName} = i
|
||||
}
|
||||
`
|
||||
@@ -1,19 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenServiceLogicContent = `
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package {PackageName}
|
||||
|
||||
import(
|
||||
{Imports}
|
||||
)
|
||||
`
|
||||
@@ -1,138 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenDaoIndexContent = `
|
||||
// =================================================================================
|
||||
// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed.
|
||||
// =================================================================================
|
||||
|
||||
package {{.TplPackageName}}
|
||||
|
||||
import (
|
||||
"{{.TplImportPrefix}}/internal"
|
||||
)
|
||||
|
||||
// {{.TplTableNameCamelLowerCase}}Dao is the data access object for the table {{.TplTableName}}.
|
||||
// You can define custom methods on it to extend its functionality as needed.
|
||||
type {{.TplTableNameCamelLowerCase}}Dao struct {
|
||||
*internal.{{.TplTableNameCamelCase}}Dao
|
||||
}
|
||||
|
||||
var (
|
||||
// {{.TplTableNameCamelCase}} is a globally accessible object for table {{.TplTableName}} operations.
|
||||
{{.TplTableNameCamelCase}} = {{.TplTableNameCamelLowerCase}}Dao{
|
||||
{{- if .TplTableSharding -}}
|
||||
internal.New{{.TplTableNameCamelCase}}Dao({{.TplTableNameCamelLowerCase}}ShardingHandler),
|
||||
{{- else -}}
|
||||
internal.New{{.TplTableNameCamelCase}}Dao(),
|
||||
{{- end -}}
|
||||
}
|
||||
)
|
||||
|
||||
{{if .TplTableSharding -}}
|
||||
// {{.TplTableNameCamelLowerCase}}ShardingHandler is the handler for sharding operations.
|
||||
// You can fill this sharding handler with your custom implementation.
|
||||
func {{.TplTableNameCamelLowerCase}}ShardingHandler(m *database.Model) *database.Model {
|
||||
m = m.Sharding(database.ShardingConfig{
|
||||
Table: database.ShardingTableConfig{
|
||||
Enable: true,
|
||||
Prefix: "{{.TplTableShardingPrefix}}",
|
||||
// Replace Rule field with your custom sharding rule.
|
||||
// Or you can use "&database.DefaultShardingRule{}" for default sharding rule.
|
||||
Rule: nil,
|
||||
},
|
||||
Schema: database.ShardingSchemaConfig{},
|
||||
})
|
||||
return m
|
||||
}
|
||||
{{- end}}
|
||||
|
||||
// Add your custom methods and functionality below.
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenDaoInternalContent = `
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {{.TplCreatedAtDatetimeStr}}
|
||||
// ==========================================================================
|
||||
|
||||
package internal
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/database"
|
||||
)
|
||||
|
||||
// {{.TplTableNameCamelCase}}Dao is the data access object for the table {{.TplTableName}}.
|
||||
type {{.TplTableNameCamelCase}}Dao struct {
|
||||
table string // table is the underlying table name of the DAO.
|
||||
group string // group is the database configuration group name of the current DAO.
|
||||
columns {{.TplTableNameCamelCase}}Columns // columns contains all the column names of Table for convenient usage.
|
||||
handlers []database.ModelHandler // handlers for customized model modification.
|
||||
}
|
||||
|
||||
// {{.TplTableNameCamelCase}}Columns defines and stores column names for the table {{.TplTableName}}.
|
||||
type {{.TplTableNameCamelCase}}Columns struct {
|
||||
{{.TplColumnDefine}}
|
||||
}
|
||||
|
||||
// {{.TplTableNameCamelLowerCase}}Columns holds the columns for the table {{.TplTableName}}.
|
||||
var {{.TplTableNameCamelLowerCase}}Columns = {{.TplTableNameCamelCase}}Columns{
|
||||
{{.TplColumnNames}}
|
||||
}
|
||||
|
||||
// New{{.TplTableNameCamelCase}}Dao creates and returns a new DAO object for table data access.
|
||||
func New{{.TplTableNameCamelCase}}Dao(handlers ...database.ModelHandler) *{{.TplTableNameCamelCase}}Dao {
|
||||
return &{{.TplTableNameCamelCase}}Dao{
|
||||
group: "{{.TplGroupName}}",
|
||||
table: "{{.TplTableName}}",
|
||||
columns: {{.TplTableNameCamelLowerCase}}Columns,
|
||||
handlers: handlers,
|
||||
}
|
||||
}
|
||||
|
||||
// DB retrieves and returns the underlying raw database management object of the current DAO.
|
||||
func (dao *{{.TplTableNameCamelCase}}Dao) DB() database.DB {
|
||||
return database.Database(dao.group)
|
||||
}
|
||||
|
||||
// Table returns the table name of the current DAO.
|
||||
func (dao *{{.TplTableNameCamelCase}}Dao) Table() string {
|
||||
return dao.table
|
||||
}
|
||||
|
||||
// Columns returns all column names of the current DAO.
|
||||
func (dao *{{.TplTableNameCamelCase}}Dao) Columns() {{.TplTableNameCamelCase}}Columns {
|
||||
return dao.columns
|
||||
}
|
||||
|
||||
// Group returns the database configuration group name of the current DAO.
|
||||
func (dao *{{.TplTableNameCamelCase}}Dao) Group() string {
|
||||
return dao.group
|
||||
}
|
||||
|
||||
// Ctx creates and returns a Model for the current DAO. It automatically sets the context for the current operation.
|
||||
func (dao *{{.TplTableNameCamelCase}}Dao) Ctx(ctx context.Context) *database.Model {
|
||||
model := dao.DB().Model(dao.table)
|
||||
for _, handler := range dao.handlers {
|
||||
model = handler(model)
|
||||
}
|
||||
return model.Safe().Ctx(ctx)
|
||||
}
|
||||
|
||||
// Transaction wraps the transaction logic using function f.
|
||||
// It rolls back the transaction and returns the error if function f returns a non-nil error.
|
||||
// It commits the transaction and returns nil if function f returns nil.
|
||||
//
|
||||
// Note: Do not commit or roll back the transaction in function f,
|
||||
// as it is automatically handled by this function.
|
||||
func (dao *{{.TplTableNameCamelCase}}Dao) Transaction(ctx context.Context, f func(ctx context.Context, tx database.TX) error) (err error) {
|
||||
return dao.Ctx(ctx).Transaction(ctx, f)
|
||||
}
|
||||
`
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenDaoDoContent = `
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {{.TplCreatedAtDatetimeStr}}
|
||||
// =================================================================================
|
||||
|
||||
package {{.TplPackageName}}
|
||||
|
||||
{{.TplPackageImports}}
|
||||
|
||||
// {{.TplTableNameCamelCase}} is the golang structure of table {{.TplTableName}} for DAO operations like Where/Data.
|
||||
{{.TplStructDefine}}
|
||||
`
|
||||
@@ -1,20 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenDaoEntityContent = `
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. {{.TplCreatedAtDatetimeStr}}
|
||||
// =================================================================================
|
||||
|
||||
package {{.TplPackageName}}
|
||||
|
||||
{{.TplPackageImports}}
|
||||
|
||||
// {{.TplTableNameCamelCase}} is the golang structure for table {{.TplTableName}}.
|
||||
{{.TplStructDefine}}
|
||||
`
|
||||
@@ -1,34 +0,0 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package consts
|
||||
|
||||
const TemplateGenTableContent = `
|
||||
// =================================================================================
|
||||
// This file is auto-generated by the GoFrame CLI tool. You may modify it as needed.
|
||||
// =================================================================================
|
||||
|
||||
package {{.TplPackageName}}
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/database"
|
||||
)
|
||||
|
||||
// {{.TplTableNameCamelCase}} defines the fields of table "{{.TplTableName}}" with their properties.
|
||||
// This map is used internally by GoFrame ORM to understand table structure.
|
||||
var {{.TplTableNameCamelCase}} = map[string]*database.TableField{
|
||||
{{.TplTableFields}}
|
||||
}
|
||||
|
||||
// Set{{.TplTableNameCamelCase}}TableFields registers the table fields definition to the database instance.
|
||||
// db: database instance that implements database.DB interface.
|
||||
// schema: optional schema/namespace name, especially for databases that support schemas.
|
||||
func Set{{.TplTableNameCamelCase}}TableFields(ctx context.Context, db database.DB, schema ...string) error {
|
||||
return db.GetCore().SetTableFields(ctx, "{{.TplTableName}}", {{.TplTableNameCamelCase}}, schema...)
|
||||
}
|
||||
`
|
||||
@@ -1,376 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/config"
|
||||
"git.magicany.cc/black1552/gin-base/database"
|
||||
_ "git.magicany.cc/black1552/gin-base/database/drivers"
|
||||
)
|
||||
|
||||
func main() {
|
||||
ctx := context.Background()
|
||||
|
||||
// 加载配置
|
||||
cfg := config.GetAllConfig()
|
||||
if cfg == nil {
|
||||
fmt.Println("❌ 错误: 配置为空")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 检查数据库配置
|
||||
dbConfigMap, ok := cfg["database"].(map[string]any)
|
||||
if !ok || len(dbConfigMap) == 0 {
|
||||
fmt.Println("❌ 错误: 未找到数据库配置")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 获取默认数据库配置
|
||||
defaultDbConfig, ok := dbConfigMap["default"].(map[string]any)
|
||||
if !ok {
|
||||
fmt.Println("❌ 错误: 未找到 default 数据库配置")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 提取配置值
|
||||
host := getStringValue(defaultDbConfig, "host", "127.0.0.1")
|
||||
port := getStringValue(defaultDbConfig, "port", "3306")
|
||||
name := getStringValue(defaultDbConfig, "name", "test")
|
||||
dbType := getStringValue(defaultDbConfig, "type", "mysql")
|
||||
|
||||
fmt.Println("=== Gin-Base DAO 代码生成工具 ===")
|
||||
fmt.Printf("📊 数据库: %s\n", name)
|
||||
fmt.Printf("🔧 类型: %s\n", dbType)
|
||||
fmt.Printf("🌐 主机: %s:%s\n\n", host, port)
|
||||
|
||||
// 初始化数据库连接
|
||||
err := initDatabaseFromMap(dbConfigMap)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 数据库初始化失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 获取数据库实例
|
||||
db := database.Database()
|
||||
|
||||
// 获取所有表
|
||||
tables, err := db.Tables(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 获取表列表失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Printf("📋 找到 %d 个表:\n", len(tables))
|
||||
for i, table := range tables {
|
||||
fmt.Printf(" %d. %s\n", i+1, table)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// 询问用户要生成的表
|
||||
var selectedTables []string
|
||||
if len(os.Args) > 1 {
|
||||
// 从命令行参数获取表名
|
||||
selectedTables = os.Args[1:]
|
||||
} else {
|
||||
// 默认生成所有表
|
||||
selectedTables = tables
|
||||
fmt.Println("💡 提示: 可以通过命令行参数指定要生成的表")
|
||||
fmt.Println(" 例如: gin-dao-gen users orders")
|
||||
}
|
||||
|
||||
// 创建输出目录
|
||||
dirs := []string{
|
||||
"./internal/dao",
|
||||
"./internal/model/do",
|
||||
"./internal/model/entity",
|
||||
"./internal/model/table",
|
||||
}
|
||||
|
||||
for _, dir := range dirs {
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
fmt.Printf("❌ 创建目录失败 %s: %v\n", dir, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个表生成代码
|
||||
for _, tableName := range selectedTables {
|
||||
fmt.Printf("\n🔨 正在生成表 [%s] 的代码...\n", tableName)
|
||||
|
||||
// 获取表字段信息
|
||||
fields, err := db.TableFields(ctx, tableName)
|
||||
if err != nil {
|
||||
fmt.Printf(" ⚠️ 获取表字段失败: %v\n", err)
|
||||
continue
|
||||
}
|
||||
|
||||
// 生成 Entity
|
||||
entityName := tableNameToStructName(tableName)
|
||||
generateEntity(tableName, entityName, fields)
|
||||
|
||||
// 生成 DO
|
||||
generateDO(tableName, entityName, fields)
|
||||
|
||||
// 生成 DAO
|
||||
generateDAO(tableName, entityName)
|
||||
|
||||
// 生成 Table
|
||||
generateTable(tableName, entityName, fields)
|
||||
|
||||
fmt.Printf(" ✅ 完成\n")
|
||||
}
|
||||
|
||||
fmt.Println("\n🎉 代码生成完成!")
|
||||
fmt.Println("📁 生成的文件位于:")
|
||||
fmt.Println(" - ./internal/dao/")
|
||||
fmt.Println(" - ./internal/model/do/")
|
||||
fmt.Println(" - ./internal/model/entity/")
|
||||
fmt.Println(" - ./internal/model/table/")
|
||||
}
|
||||
|
||||
// 从 Map 初始化数据库
|
||||
func initDatabaseFromMap(dbConfigMap map[string]any) error {
|
||||
for name, nodeConfig := range dbConfigMap {
|
||||
nodeMap, ok := nodeConfig.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
configNode := database.ConfigNode{
|
||||
Host: getStringValue(nodeMap, "host", "127.0.0.1"),
|
||||
Port: getStringValue(nodeMap, "port", "3306"),
|
||||
User: getStringValue(nodeMap, "user", "root"),
|
||||
Pass: getStringValue(nodeMap, "pass", ""),
|
||||
Name: getStringValue(nodeMap, "name", ""),
|
||||
Type: getStringValue(nodeMap, "type", "mysql"),
|
||||
Role: database.Role(getStringValue(nodeMap, "role", "master")),
|
||||
Debug: getBoolValue(nodeMap, "debug", false),
|
||||
Prefix: getStringValue(nodeMap, "prefix", ""),
|
||||
Charset: getStringValue(nodeMap, "charset", "utf8"),
|
||||
}
|
||||
|
||||
if err := database.AddConfigNode(name, configNode); err != nil {
|
||||
return fmt.Errorf("add config node %s failed: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// 辅助函数:从 map 中获取字符串值
|
||||
func getStringValue(m map[string]any, key string, defaultValue string) string {
|
||||
if val, ok := m[key]; ok {
|
||||
if str, ok := val.(string); ok {
|
||||
return str
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// 辅助函数:从 map 中获取布尔值
|
||||
func getBoolValue(m map[string]any, key string, defaultValue bool) bool {
|
||||
if val, ok := m[key]; ok {
|
||||
if b, ok := val.(bool); ok {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// 表名转结构体名
|
||||
func tableNameToStructName(tableName string) string {
|
||||
parts := strings.Split(tableName, "_")
|
||||
var result strings.Builder
|
||||
for _, part := range parts {
|
||||
if len(part) > 0 {
|
||||
result.WriteString(strings.ToUpper(part[:1]))
|
||||
result.WriteString(part[1:])
|
||||
}
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// 生成 Entity 文件
|
||||
func generateEntity(tableName, entityName string, fields map[string]*database.TableField) {
|
||||
filename := fmt.Sprintf("./internal/model/entity/%s.go", tableName)
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package entity\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %s represents the entity for table %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("type %s struct {\n", entityName))
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToStructName(field.Name)
|
||||
goType := dbTypeToGoType(field.Type)
|
||||
jsonTag := field.Name
|
||||
|
||||
content.WriteString(fmt.Sprintf("\t%s %s `json:\"%s\" description:\"%s\"`\n",
|
||||
fieldName, goType, jsonTag, field.Comment))
|
||||
}
|
||||
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 Entity: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 DO 文件
|
||||
func generateDO(tableName, entityName string, fields map[string]*database.TableField) {
|
||||
filename := fmt.Sprintf("./internal/model/do/%s.go", tableName)
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package do\n\n")
|
||||
content.WriteString("import \"github.com/gogf/gf/v2/frame/g\"\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %s represents the data object for table %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("type %s struct {\n\tg.Meta `orm:\"table:%s, do:true\"`\n\n", entityName, tableName))
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToStructName(field.Name)
|
||||
goType := dbTypeToGoType(field.Type)
|
||||
|
||||
content.WriteString(fmt.Sprintf("\t%s *%s `json:\"%s,omitempty\"`\n",
|
||||
fieldName, goType, field.Name))
|
||||
}
|
||||
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 DO: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 DAO 文件
|
||||
func generateDAO(tableName, entityName string) {
|
||||
filename := fmt.Sprintf("./internal/dao/%s.go", tableName)
|
||||
lowerName := strings.ToLower(entityName[:1]) + entityName[1:]
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package dao\n\n")
|
||||
content.WriteString("import (\n")
|
||||
content.WriteString("\t\"git.magicany.cc/black1552/gin-base/database\"\n")
|
||||
content.WriteString(fmt.Sprintf("\t\"git.magicany.cc/black1552/gin-base/internal/model/entity\"\n"))
|
||||
content.WriteString(")\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %s is the DAO for table %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("var %s = New%s()\n\n", lowerName, entityName))
|
||||
content.WriteString(fmt.Sprintf("// %s creates and returns a new DAO instance\n", entityName))
|
||||
content.WriteString(fmt.Sprintf("func New%s() *%sDao {\n", entityName, entityName))
|
||||
content.WriteString(fmt.Sprintf("\treturn &%sDao{\n", entityName))
|
||||
content.WriteString("\t\ttable: \"" + tableName + "\",\n")
|
||||
content.WriteString("\t}\n")
|
||||
content.WriteString("}\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %sDao is the data access object for %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("type %sDao struct {\n", entityName))
|
||||
content.WriteString("\ttable string\n")
|
||||
content.WriteString("}\n\n")
|
||||
content.WriteString("// Table returns the table name\n")
|
||||
content.WriteString(fmt.Sprintf("func (d *%sDao) Table() string {\n", entityName))
|
||||
content.WriteString("\treturn d.table\n")
|
||||
content.WriteString("}\n\n")
|
||||
content.WriteString("// DB returns the database instance\n")
|
||||
content.WriteString("func (d *DB) DB() database.DB {\n")
|
||||
content.WriteString("\treturn database.Database()\n")
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 DAO: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 Table 文件
|
||||
func generateTable(tableName, entityName string, fields map[string]*database.TableField) {
|
||||
filename := fmt.Sprintf("./internal/model/table/%s.go", tableName)
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package table\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString("const (\n")
|
||||
content.WriteString(fmt.Sprintf("\t// %s is the table name\n", entityName))
|
||||
content.WriteString(fmt.Sprintf("\t%s = \"%s\"\n", entityName, tableName))
|
||||
content.WriteString(")\n\n")
|
||||
content.WriteString("// Columns defines all columns of the table\n")
|
||||
content.WriteString("var Columns = struct {\n")
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToConstName(field.Name)
|
||||
content.WriteString(fmt.Sprintf("\t%s string\n", fieldName))
|
||||
}
|
||||
content.WriteString("}{\n")
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToConstName(field.Name)
|
||||
content.WriteString(fmt.Sprintf("\t%s: \"%s\",\n", fieldName, field.Name))
|
||||
}
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 Table: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 字段名转结构体字段名
|
||||
func fieldNameToStructName(fieldName string) string {
|
||||
parts := strings.Split(fieldName, "_")
|
||||
var result strings.Builder
|
||||
for _, part := range parts {
|
||||
if len(part) > 0 {
|
||||
result.WriteString(strings.ToUpper(part[:1]))
|
||||
result.WriteString(part[1:])
|
||||
}
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// 字段名转常量名
|
||||
func fieldNameToConstName(fieldName string) string {
|
||||
parts := strings.Split(fieldName, "_")
|
||||
var result strings.Builder
|
||||
for i, part := range parts {
|
||||
if i > 0 {
|
||||
result.WriteString("_")
|
||||
}
|
||||
result.WriteString(strings.ToUpper(part))
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// 数据库类型转 Go 类型
|
||||
func dbTypeToGoType(dbType string) string {
|
||||
dbType = strings.ToLower(dbType)
|
||||
|
||||
switch {
|
||||
case strings.Contains(dbType, "int"):
|
||||
if strings.Contains(dbType, "bigint") {
|
||||
return "int64"
|
||||
}
|
||||
return "int"
|
||||
case strings.Contains(dbType, "float"), strings.Contains(dbType, "double"), strings.Contains(dbType, "decimal"):
|
||||
return "float64"
|
||||
case strings.Contains(dbType, "bool"):
|
||||
return "bool"
|
||||
case strings.Contains(dbType, "datetime"), strings.Contains(dbType, "timestamp"):
|
||||
return "*gtime.Time"
|
||||
case strings.Contains(dbType, "date"):
|
||||
return "*gtime.Time"
|
||||
case strings.Contains(dbType, "text"), strings.Contains(dbType, "char"), strings.Contains(dbType, "varchar"):
|
||||
return "string"
|
||||
case strings.Contains(dbType, "blob"), strings.Contains(dbType, "binary"):
|
||||
return "[]byte"
|
||||
default:
|
||||
return "string"
|
||||
}
|
||||
}
|
||||
+44
-330
@@ -4,10 +4,9 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"git.magicany.cc/black1552/gin-base/cmd/gendao"
|
||||
"git.magicany.cc/black1552/gin-base/config"
|
||||
"git.magicany.cc/black1552/gin-base/database"
|
||||
_ "git.magicany.cc/black1552/gin-base/database/drivers"
|
||||
)
|
||||
|
||||
@@ -39,6 +38,8 @@ func main() {
|
||||
host := getStringValue(defaultDbConfig, "host", "127.0.0.1")
|
||||
port := getStringValue(defaultDbConfig, "port", "3306")
|
||||
name := getStringValue(defaultDbConfig, "name", "test")
|
||||
user := getStringValue(defaultDbConfig, "user", "root")
|
||||
pass := getStringValue(defaultDbConfig, "pass", "")
|
||||
dbType := getStringValue(defaultDbConfig, "type", "mysql")
|
||||
|
||||
fmt.Println("=== Gin-Base DAO 代码生成工具 ===")
|
||||
@@ -46,144 +47,50 @@ func main() {
|
||||
fmt.Printf("🔧 类型: %s\n", dbType)
|
||||
fmt.Printf("🌐 主机: %s:%s\n\n", host, port)
|
||||
|
||||
// 初始化数据库连接
|
||||
err := initDatabaseFromMap(dbConfigMap)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 数据库初始化失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
// 构建数据库连接字符串
|
||||
link := fmt.Sprintf("mysql:%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=true&loc=Local",
|
||||
user, pass, host, port, name,
|
||||
)
|
||||
|
||||
// 获取数据库实例(使用 default 组)
|
||||
db := database.Database("default")
|
||||
|
||||
// 调试信息:打印当前使用的数据库名称
|
||||
config := db.GetConfig()
|
||||
if config != nil {
|
||||
fmt.Printf("🔍 调试: 当前数据库名 = %s, 类型 = %s\n", config.Name, config.Type)
|
||||
}
|
||||
|
||||
// 获取所有表
|
||||
tables, err := db.Tables(ctx)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 获取表列表失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// 如果没找到表,尝试直接查询验证
|
||||
if len(tables) == 0 {
|
||||
fmt.Println("⚠️ 警告: 未找到任何表,尝试直接查询...")
|
||||
result, err := db.Query(ctx, "SHOW TABLES")
|
||||
if err != nil {
|
||||
fmt.Printf("❌ 直接查询失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("🔍 直接查询结果: %d 行\n", len(result))
|
||||
for _, row := range result {
|
||||
fmt.Printf(" - %v\n", row)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("📋 找到 %d 个表:\n", len(tables))
|
||||
for i, table := range tables {
|
||||
fmt.Printf(" %d. %s\n", i+1, table)
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
// 询问用户要生成的表
|
||||
var selectedTables []string
|
||||
// 准备表名参数
|
||||
tablesArg := ""
|
||||
if len(os.Args) > 1 {
|
||||
// 从命令行参数获取表名
|
||||
selectedTables = os.Args[1:]
|
||||
tablesArg = joinStrings(os.Args[1:], ",")
|
||||
fmt.Printf("📋 指定生成表: %s\n\n", tablesArg)
|
||||
} else {
|
||||
// 默认生成所有表
|
||||
selectedTables = tables
|
||||
fmt.Println("💡 提示: 可以通过命令行参数指定要生成的表")
|
||||
fmt.Println(" 例如: gin-dao-gen users orders")
|
||||
fmt.Println(" 例如: gin-dao-gen users orders\n")
|
||||
}
|
||||
|
||||
// 创建输出目录
|
||||
dirs := []string{
|
||||
"./internal/dao",
|
||||
"./internal/model/do",
|
||||
"./internal/model/entity",
|
||||
"./internal/model/table",
|
||||
// 调用 gendao 的 Dao 函数生成代码
|
||||
genDao := gendao.CGenDao{}
|
||||
input := gendao.CGenDaoInput{
|
||||
Link: link,
|
||||
Tables: tablesArg,
|
||||
Path: "./",
|
||||
DaoPath: "dao",
|
||||
DoPath: "model/do",
|
||||
EntityPath: "model/entity",
|
||||
TablePath: "model/table",
|
||||
Group: "default",
|
||||
JsonCase: "CamelLower",
|
||||
DescriptionTag: true,
|
||||
GenTable: true,
|
||||
}
|
||||
|
||||
for _, dir := range dirs {
|
||||
if err := os.MkdirAll(dir, 0755); err != nil {
|
||||
fmt.Printf("❌ 创建目录失败 %s: %v\n", dir, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
// 为每个表生成代码
|
||||
for _, tableName := range selectedTables {
|
||||
fmt.Printf("\n🔨 正在生成表 [%s] 的代码...\n", tableName)
|
||||
|
||||
// 获取表字段信息
|
||||
fields, err := db.TableFields(ctx, tableName)
|
||||
if err != nil {
|
||||
fmt.Printf(" ⚠️ 获取表字段失败: %v\n", err)
|
||||
return // 使用 return 而不是 continue
|
||||
}
|
||||
|
||||
// 调试:打印字段信息
|
||||
fmt.Printf(" 🔍 调试: 找到 %d 个字段\n", len(fields))
|
||||
for name, field := range fields {
|
||||
fmt.Printf(" - %s: %s (%s)\n", name, field.Type, field.Comment)
|
||||
}
|
||||
|
||||
// 生成 Entity
|
||||
entityName := tableNameToStructName(tableName)
|
||||
generateEntity(tableName, entityName, fields)
|
||||
|
||||
// 生成 DO
|
||||
generateDO(tableName, entityName, fields)
|
||||
|
||||
// 生成 DAO
|
||||
generateDAO(tableName, entityName)
|
||||
|
||||
// 生成 Table
|
||||
generateTable(tableName, entityName, fields)
|
||||
|
||||
fmt.Printf(" ✅ 完成\n")
|
||||
fmt.Println("🔨 开始生成代码...")
|
||||
_, err := genDao.Dao(ctx, input)
|
||||
if err != nil {
|
||||
fmt.Printf("\n❌ 代码生成失败: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("\n🎉 代码生成完成!")
|
||||
fmt.Println("📁 生成的文件位于:")
|
||||
fmt.Println(" - ./internal/dao/")
|
||||
fmt.Println(" - ./internal/model/do/")
|
||||
fmt.Println(" - ./internal/model/entity/")
|
||||
fmt.Println(" - ./internal/model/table/")
|
||||
}
|
||||
|
||||
// 从 Map 初始化数据库
|
||||
func initDatabaseFromMap(dbConfigMap map[string]any) error {
|
||||
for name, nodeConfig := range dbConfigMap {
|
||||
nodeMap, ok := nodeConfig.(map[string]any)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
configNode := database.ConfigNode{
|
||||
Host: getStringValue(nodeMap, "host", "127.0.0.1"),
|
||||
Port: getStringValue(nodeMap, "port", "3306"),
|
||||
User: getStringValue(nodeMap, "user", "root"),
|
||||
Pass: getStringValue(nodeMap, "pass", ""),
|
||||
Name: getStringValue(nodeMap, "name", ""),
|
||||
Type: getStringValue(nodeMap, "type", "mysql"),
|
||||
Role: database.Role(getStringValue(nodeMap, "role", "master")),
|
||||
Debug: getBoolValue(nodeMap, "debug", false),
|
||||
Prefix: getStringValue(nodeMap, "prefix", ""),
|
||||
Charset: getStringValue(nodeMap, "charset", "utf8"),
|
||||
}
|
||||
|
||||
if err := database.AddConfigNode(name, configNode); err != nil {
|
||||
return fmt.Errorf("add config node %s failed: %w", name, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
fmt.Println(" - ./dao/")
|
||||
fmt.Println(" - ./model/do/")
|
||||
fmt.Println(" - ./model/entity/")
|
||||
fmt.Println(" - ./model/table/")
|
||||
}
|
||||
|
||||
// 辅助函数:从 map 中获取字符串值
|
||||
@@ -196,207 +103,14 @@ func getStringValue(m map[string]any, key string, defaultValue string) string {
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// 辅助函数:从 map 中获取布尔值
|
||||
func getBoolValue(m map[string]any, key string, defaultValue bool) bool {
|
||||
if val, ok := m[key]; ok {
|
||||
if b, ok := val.(bool); ok {
|
||||
return b
|
||||
}
|
||||
}
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
// 表名转结构体名
|
||||
func tableNameToStructName(tableName string) string {
|
||||
parts := strings.Split(tableName, "_")
|
||||
var result strings.Builder
|
||||
for _, part := range parts {
|
||||
if len(part) > 0 {
|
||||
result.WriteString(strings.ToUpper(part[:1]))
|
||||
result.WriteString(part[1:])
|
||||
}
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// 生成 Entity 文件
|
||||
func generateEntity(tableName, entityName string, fields map[string]*database.TableField) {
|
||||
filename := fmt.Sprintf("./internal/model/entity/%s.go", tableName)
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package entity\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %s represents the entity for table %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("type %s struct {\n", entityName))
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToStructName(field.Name)
|
||||
goType := dbTypeToGoType(field.Type)
|
||||
jsonTag := field.Name
|
||||
|
||||
content.WriteString(fmt.Sprintf("\t%s %s `json:\"%s\" description:\"%s\"`\n",
|
||||
fieldName, goType, jsonTag, field.Comment))
|
||||
}
|
||||
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 Entity: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 DO 文件
|
||||
func generateDO(tableName, entityName string, fields map[string]*database.TableField) {
|
||||
filename := fmt.Sprintf("./internal/model/do/%s.go", tableName)
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package do\n\n")
|
||||
content.WriteString("import \"github.com/gogf/gf/v2/frame/g\"\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %s represents the data object for table %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("type %s struct {\n\tg.Meta `orm:\"table:%s, do:true\"`\n\n", entityName, tableName))
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToStructName(field.Name)
|
||||
goType := dbTypeToGoType(field.Type)
|
||||
|
||||
content.WriteString(fmt.Sprintf("\t%s *%s `json:\"%s,omitempty\"`\n",
|
||||
fieldName, goType, field.Name))
|
||||
}
|
||||
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 DO: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 DAO 文件
|
||||
func generateDAO(tableName, entityName string) {
|
||||
filename := fmt.Sprintf("./internal/dao/%s.go", tableName)
|
||||
lowerName := strings.ToLower(entityName[:1]) + entityName[1:]
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package dao\n\n")
|
||||
content.WriteString("import (\n")
|
||||
content.WriteString("\t\"git.magicany.cc/black1552/gin-base/database\"\n")
|
||||
content.WriteString(fmt.Sprintf("\t\"git.magicany.cc/black1552/gin-base/internal/model/entity\"\n"))
|
||||
content.WriteString(")\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %s is the DAO for table %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("var %s = New%s()\n\n", lowerName, entityName))
|
||||
content.WriteString(fmt.Sprintf("// %s creates and returns a new DAO instance\n", entityName))
|
||||
content.WriteString(fmt.Sprintf("func New%s() *%sDao {\n", entityName, entityName))
|
||||
content.WriteString(fmt.Sprintf("\treturn &%sDao{\n", entityName))
|
||||
content.WriteString("\t\ttable: \"" + tableName + "\",\n")
|
||||
content.WriteString("\t}\n")
|
||||
content.WriteString("}\n\n")
|
||||
content.WriteString(fmt.Sprintf("// %sDao is the data access object for %s\n", entityName, tableName))
|
||||
content.WriteString(fmt.Sprintf("type %sDao struct {\n", entityName))
|
||||
content.WriteString("\ttable string\n")
|
||||
content.WriteString("}\n\n")
|
||||
content.WriteString("// Table returns the table name\n")
|
||||
content.WriteString(fmt.Sprintf("func (d *%sDao) Table() string {\n", entityName))
|
||||
content.WriteString("\treturn d.table\n")
|
||||
content.WriteString("}\n\n")
|
||||
content.WriteString("// DB returns the database instance\n")
|
||||
content.WriteString("func (d *DB) DB() database.DB {\n")
|
||||
content.WriteString("\treturn database.Database()\n")
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 DAO: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 生成 Table 文件
|
||||
func generateTable(tableName, entityName string, fields map[string]*database.TableField) {
|
||||
filename := fmt.Sprintf("./internal/model/table/%s.go", tableName)
|
||||
|
||||
var content strings.Builder
|
||||
content.WriteString("package table\n\n")
|
||||
content.WriteString("// Auto-generated by gin-base gen dao tool\n\n")
|
||||
content.WriteString("const (\n")
|
||||
content.WriteString(fmt.Sprintf("\t// %s is the table name\n", entityName))
|
||||
content.WriteString(fmt.Sprintf("\t%s = \"%s\"\n", entityName, tableName))
|
||||
content.WriteString(")\n\n")
|
||||
content.WriteString("// Columns defines all columns of the table\n")
|
||||
content.WriteString("var Columns = struct {\n")
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToConstName(field.Name)
|
||||
content.WriteString(fmt.Sprintf("\t%s string\n", fieldName))
|
||||
}
|
||||
content.WriteString("}{\n")
|
||||
|
||||
for _, field := range fields {
|
||||
fieldName := fieldNameToConstName(field.Name)
|
||||
content.WriteString(fmt.Sprintf("\t%s: \"%s\",\n", fieldName, field.Name))
|
||||
}
|
||||
content.WriteString("}\n")
|
||||
|
||||
if err := os.WriteFile(filename, []byte(content.String()), 0644); err != nil {
|
||||
fmt.Printf(" ❌ 写入文件失败: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf(" 📄 生成 Table: %s\n", filename)
|
||||
}
|
||||
}
|
||||
|
||||
// 字段名转结构体字段名
|
||||
func fieldNameToStructName(fieldName string) string {
|
||||
parts := strings.Split(fieldName, "_")
|
||||
var result strings.Builder
|
||||
for _, part := range parts {
|
||||
if len(part) > 0 {
|
||||
result.WriteString(strings.ToUpper(part[:1]))
|
||||
result.WriteString(part[1:])
|
||||
}
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// 字段名转常量名
|
||||
func fieldNameToConstName(fieldName string) string {
|
||||
parts := strings.Split(fieldName, "_")
|
||||
var result strings.Builder
|
||||
for i, part := range parts {
|
||||
if i > 0 {
|
||||
result.WriteString("_")
|
||||
}
|
||||
result.WriteString(strings.ToUpper(part))
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
// 数据库类型转 Go 类型
|
||||
func dbTypeToGoType(dbType string) string {
|
||||
dbType = strings.ToLower(dbType)
|
||||
|
||||
switch {
|
||||
case strings.Contains(dbType, "int"):
|
||||
if strings.Contains(dbType, "bigint") {
|
||||
return "int64"
|
||||
}
|
||||
return "int"
|
||||
case strings.Contains(dbType, "float"), strings.Contains(dbType, "double"), strings.Contains(dbType, "decimal"):
|
||||
return "float64"
|
||||
case strings.Contains(dbType, "bool"):
|
||||
return "bool"
|
||||
case strings.Contains(dbType, "datetime"), strings.Contains(dbType, "timestamp"):
|
||||
return "*gtime.Time"
|
||||
case strings.Contains(dbType, "date"):
|
||||
return "*gtime.Time"
|
||||
case strings.Contains(dbType, "text"), strings.Contains(dbType, "char"), strings.Contains(dbType, "varchar"):
|
||||
return "string"
|
||||
case strings.Contains(dbType, "blob"), strings.Contains(dbType, "binary"):
|
||||
return "[]byte"
|
||||
default:
|
||||
return "string"
|
||||
// 辅助函数:连接字符串数组
|
||||
func joinStrings(strs []string, sep string) string {
|
||||
if len(strs) == 0 {
|
||||
return ""
|
||||
}
|
||||
result := strs[0]
|
||||
for i := 1; i < len(strs); i++ {
|
||||
result += sep + strs[i]
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user