背景
一般的业务开发经常需要设计表结构,然后一系列的增删改查等。为了能够稍微减少这些重复劳动,写了一个简单的脚本自动生成表结构信息。
依赖
- Golang(需要支持Go Modules 和 embed)
- sqlx
项目介绍
Github 地址 https://github.com/vnotes/gendb
├── go.mod
├── go.sum
├── main.go
├── model
│ ├── db2.tmpl
│ ├── db.tmpl
│ ├── format.go
│ ├── tablesapi
│ │ └── TABLES_gen.go
│ ├── TABLES_gen.go
│ └── template.go
├── mysqldb
│ ├── mysql.go
│ ├── table.go
│ └── table_info.go
└── README.md
- mysqldb 是 MySQL 的数据库连接信息
- model 是 CRUD 模板。提供了 2 个:db 和 db2
- model/TABLES_gen.go model/tablesapi/TABLES_gen.go 是 2 个模板的例子。
效果
CREATE TABLE `sale_order` (
`id` bigint NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`order_name` varchar(32) NOT NULL DEFAULT '' COMMENT '订单号',
`order_line` bigint NOT NULL DEFAULT '0' COMMENT '订单行',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
`state` tinyint NOT NULL DEFAULT '0' COMMENT '订单状态',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_order_line` (`order_line`),
UNIQUE KEY `uk_order_name` (`order_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='销售订单信息';
target=sale_order type=2 go run main.go -u root -h 127.0.0.1 -p root -d dev
- target是目标数据库表
- type为2是用模板2.
- 其他的就是数据库信息了。
生成
// Code generated by gendb; DO NOT EDIT.
package saleorderapi
import (
"context"
"database/sql"
"fmt"
"strings"
"time"
"github.com/jmoiron/sqlx"
)
const TableName = "sale_order"
type column struct {
CreateTime string
Id string
OrderLine string
OrderName string
State string
UpdateTime string
}
var (
Col = &column{
CreateTime: "create_time",
Id: "id",
OrderLine: "order_line",
OrderName: "order_name",
State: "state",
UpdateTime: "update_time",
}
)
type Entity struct {
CreateTime time.Time `db:"create_time"` // 创建时间
Id int64 `db:"id"` // 自增主键
OrderLine int64 `db:"order_line"` // 订单行
OrderName string `db:"order_name"` // 订单号
State int8 `db:"state"` // 订单状态
UpdateTime time.Time `db:"update_time"` // 更新时间
}
type model interface {
dbInsert(context.Context, ...map[string]interface{}) (sql.Result, error)
dbSelect(context.Context, map[string]interface{}, ...string) ([]*Entity, error)
}
type impl struct {
db sqlx.ExtContext
}
var i *impl
func SetCli(db sqlx.ExtContext) {
i = &impl{db: db}
}
func GetCli() model {
return i
}
var _ model = (*impl)(nil)
func (i *impl) dbInsert(ctx context.Context, values ...map[string]interface{}) (sql.Result, error) {
if len(values) == 0 {
return nil, nil
}
var fields []string
for k := range values[0] {
fields = append(fields, k)
}
k := strings.Join(fields, ",")
v := ":" + strings.Join(fields, ",:")
s := fmt.Sprintf("INSERT INTO sale_order (%s) VALUES (%s);", k, v)
result, err := sqlx.NamedExecContext(ctx, i.db, s, values)
if err != nil {
return nil, fmt.Errorf("insert error %w", err)
}
return result, nil
}
func (i *impl) dbSelect(ctx context.Context, values map[string]interface{}, fields ...string) ([]*Entity, error) {
var result []*Entity
var s []string
var args []interface{}
for k, v := range values {
s = append(s, fmt.Sprintf("%s=?", k))
args = append(args, v)
}
var query = fmt.Sprintf("SELECT %s FROM sale_order WHERE %s", strings.Join(fields, ","), strings.Join(s, " and "))
err := sqlx.SelectContext(ctx, i.db, &result, query, args...)
if err != nil {
return nil, fmt.Errorf("select error %w", err)
}
return result, nil
}
简书如何折叠代码??
个人疑惑:
对于上述生成的代码,如何使用就看个人。个人习惯的开发模式为
model
目录下的二级目录是表的增删改查和表相关的信息。因为目录本身带有 namespace 的概念,因此很多变量省去了表这个主体,例如 Col
,Cli
等。而不是 saleOrderCol
这些。
然后同级别是 external
,外部依赖等等。
就看目前结构看个人开发习惯和公司规定,统一就 Okay
至于 Cli
如何初始化就看自己的写法了....