背景
一般的業(yè)務(wù)開發(fā)經(jīng)常需要設(shè)計(jì)表結(jié)構(gòu),然后一系列的增刪改查等。為了能夠稍微減少這些重復(fù)勞動,寫了一個簡單的腳本自動生成表結(jié)構(gòu)信息。
依賴
- Golang(需要支持Go Modules 和 embed)
- sqlx
項(xiàng)目介紹
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 的數(shù)據(jù)庫連接信息
- 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 '創(chuàng)建時間',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間',
`state` tinyint NOT NULL DEFAULT '0' COMMENT '訂單狀態(tài)',
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是目標(biāo)數(shù)據(jù)庫表
- type為2是用模板2.
- 其他的就是數(shù)據(jù)庫信息了。
生成
// 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"` // 創(chuàng)建時間
Id int64 `db:"id"` // 自增主鍵
OrderLine int64 `db:"order_line"` // 訂單行
OrderName string `db:"order_name"` // 訂單號
State int8 `db:"state"` // 訂單狀態(tài)
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
}
簡書如何折疊代碼??
個人疑惑:
對于上述生成的代碼,如何使用就看個人。個人習(xí)慣的開發(fā)模式為
model目錄下的二級目錄是表的增刪改查和表相關(guān)的信息。因?yàn)槟夸洷旧韼в?namespace 的概念,因此很多變量省去了表這個主體,例如 Col,Cli 等。而不是 saleOrderCol 這些。
然后同級別是 external,外部依賴等等。
就看目前結(jié)構(gòu)看個人開發(fā)習(xí)慣和公司規(guī)定,統(tǒng)一就 Okay
至于 Cli 如何初始化就看自己的寫法了....