README
¶
gorm_dao_generator
1.Introduction
gorm_dao_generator is a tool for automatically generating Mysql Data Access Object.
2.Advantage
-
Provides a unified generation scheme for database fields, avoiding the problem of database fields that can be seen everywhere in business codes.
-
Provides various database operation interfaces including Insert, Delete, Update, Count, Sum, Avg, First, Last, FindOne, FindMany, etc.
-
Provides the ability to expand the database operation interface.
-
Provides two package solutions: subcontracting and non-subcontracting.
-
Supports customization of directory and file name styles.
3.Requirements
- Go 1.20+
- MySQL 8.0+
4.Download and install
go env -w GOSUMDB=off
go install github.com/dawnsgo/gorm_dao_generator@latest
go env -w GOSUMDB=on
5.Usage
Usage of gorm_dao_generator:
gorm_dao_generator [flags] -model-dir=. -model-names=M[:t],M[:t] -dao-dir=./dao
For more information, see:
https://github.com/dawnsgo/gorm_dao_generator
Flags:
-dao-dir string
specify the output directory of dao files; must be set
-dao-pkg-path string
specify the package path corresponding to the output directory of the dao files; automatically generated by default
-file-style string
specify the generation style for file; options: kebab | underscore | lower | camel | pascal; default is underscore (default "underscore")
-model-dir string
specify the model directory; must be set
-model-names string
specify one or more modelName[:tableName] pairs; must be set
-model-pkg-alias string
specify a model package alias; default no alias
-model-pkg-path string
specify the package path corresponding to the model directory; automatically calculated by default
-sub-pkg-enable
specify whether to enable sub-pkg; default disable
-sub-pkg-style string
specify the generation style for sub-pkg; options: kebab | underscore | lower | camel | pascal; default is kebab (default "kebab")
6.Example
6-1.Create model
File Location: example/model/mail.go
package model
import (
"time"
)
//go:generate gorm_dao_generator -model-dir=. -model-names=Mail -dao-dir=../dao/
type Mail struct {
ID int `gorm:"column:id"` // 邮件ID
Title string `gorm:"column:title"` // 邮件标题
Content string `gorm:"column:content"` // 邮件内容
Sender int64 `gorm:"column:sender"` // 邮件发送者
Receiver int64 `gorm:"column:receiver"` // 邮件接受者
Status int `gorm:"column:status"` // 邮件状态
SendTime time.Time `gorm:"column:send_time"` // 发送时间
}
6-2.Generate dao files
go generate ./...
6-3.Generated dao file example
File Location: example/dao/internal/mail.go
// --------------------------------------------------------------------------------------------
// The following code is automatically generated by the gorm_dao_generator tool.
// Please do not modify this code manually to avoid being overwritten in the next generation.
// For more tool details, please click the link to view https://github.com/dawnsgo/gorm_dao_generator
// --------------------------------------------------------------------------------------------
package internal
import (
"context"
"errors"
"fmt"
modelpkg "github.com/dawnsgo/gorm_dao_generator/example/model"
"gorm.io/gorm"
"strconv"
"strings"
)
type MailOrderBy struct {
Column string
Order string
}
type MailFilterFunc func(cols *MailColumns) interface{}
type MailUpdateFunc func(cols *MailColumns) interface{}
type MailColumnFunc func(cols *MailColumns) []string
type MailOrderFunc func(cols *MailColumns) []MailOrderBy
type Mail struct {
Columns *MailColumns
Database *gorm.DB
TableName string
}
type MailColumns struct {
ID string // 邮件ID
Title string // 邮件标题
Content string // 邮件内容
Sender string // 邮件发送者
Receiver string // 邮件接受者
Status string // 邮件状态
SendTime string // 发送时间
}
var mailColumns = &MailColumns{
ID: "id", // 邮件ID
Title: "title", // 邮件标题
Content: "content", // 邮件内容
Sender: "sender", // 邮件发送者
Receiver: "receiver", // 邮件接受者
Status: "status", // 邮件状态
SendTime: "send_time", // 发送时间
}
func NewMail(db *gorm.DB) *Mail {
dao := &Mail{}
dao.Columns = mailColumns
dao.TableName = "mail"
dao.Database = db
return dao
}
// New create a new instance and return
func (dao *Mail) New(tx *gorm.DB) *Mail {
d := &Mail{}
d.Columns = dao.Columns
d.TableName = dao.TableName
d.Database = tx
return d
}
// Table create a new table db instance
func (dao *Mail) Table(ctx context.Context) *gorm.DB {
return dao.Database.Model(&modelpkg.Mail{}).Table(dao.TableName).WithContext(ctx)
}
// Insert executes an insert command to insert multiple documents into the collection.
func (dao *Mail) Insert(ctx context.Context, models ...*modelpkg.Mail) (int64, error) {
if len(models) == 0 {
return 0, errors.New("models is empty")
}
var rst *gorm.DB
if len(models) == 1 {
rst = dao.Table(ctx).Create(models[0])
} else {
rst = dao.Table(ctx).Create(models)
}
return rst.RowsAffected, rst.Error
}
// Delete executes a delete command to delete at most one document from the collection.
func (dao *Mail) Delete(ctx context.Context, filterFunc ...MailFilterFunc) (int64, error) {
db := dao.Table(ctx)
if len(filterFunc) > 0 && filterFunc[0] != nil {
db = db.Where(filterFunc[0](dao.Columns))
}
rst := db.Delete(&modelpkg.Mail{})
return rst.RowsAffected, rst.Error
}
// Update executes an update command to update documents in the collection.
func (dao *Mail) Update(ctx context.Context, filterFunc MailFilterFunc, updateFunc MailUpdateFunc, columnFunc ...MailColumnFunc) (int64, error) {
db := dao.Table(ctx)
if filterFunc != nil {
db = db.Where(filterFunc(dao.Columns))
}
if len(columnFunc) > 0 && columnFunc[0] != nil {
db = db.Select(columnFunc[0](dao.Columns))
}
if updateFunc != nil {
rst := db.Updates(updateFunc(dao.Columns))
return rst.RowsAffected, rst.Error
}
return 0, nil
}
// Count returns the number of documents in the collection.
func (dao *Mail) Count(ctx context.Context, filterFunc ...MailFilterFunc) (count int64, err error) {
db := dao.Table(ctx)
if len(filterFunc) > 0 && filterFunc[0] != nil {
db = db.Where(filterFunc[0](dao.Columns))
}
err = db.Count(&count).Error
return
}
// Sum returns the sum of the given field.
func (dao *Mail) Sum(ctx context.Context, columnFunc MailColumnFunc, filterFunc ...MailFilterFunc) (sums []float64, err error) {
columns := columnFunc(dao.Columns)
if len(columns) == 0 {
return
}
fields := make([]string, len(columns))
for i, column := range columns {
fields[i] = fmt.Sprintf("COALESCE(SUM(%s), 0) as `sum_%d`", column, i)
}
db := dao.Table(ctx).Select(strings.Join(fields, ","))
if len(filterFunc) > 0 && filterFunc[0] != nil {
db = db.Where(filterFunc[0](dao.Columns))
}
rst := make(map[string]interface{}, len(columns))
if err = db.Scan(&rst).Error; err != nil {
return
}
for i := range columns {
val, _ := rst[fmt.Sprintf("sum_%d", i)]
sum, _ := strconv.ParseFloat(val.(string), 64)
sums = append(sums, sum)
}
return
}
// Avg returns the avg of the given field.
func (dao *Mail) Avg(ctx context.Context, columnFunc MailColumnFunc, filterFunc ...MailFilterFunc) (avgs []float64, err error) {
columns := columnFunc(dao.Columns)
if len(columns) == 0 {
return
}
fields := make([]string, len(columns))
for i, column := range columns {
fields[i] = fmt.Sprintf("COALESCE(AVG(%s), 0) as `avg_%d`", column, i)
}
db := dao.Table(ctx).Select(strings.Join(fields, ","))
if len(filterFunc) > 0 && filterFunc[0] != nil {
db = db.Where(filterFunc[0](dao.Columns))
}
rst := make(map[string]interface{}, len(columns))
if err = db.Scan(&rst).Error; err != nil {
return
}
for i := range columns {
val, _ := rst[fmt.Sprintf("avg_%d", i)]
avg, _ := strconv.ParseFloat(val.(string), 64)
avgs = append(avgs, avg)
}
return
}
// First executes a first command and returns a model for one record in the table.
func (dao *Mail) First(ctx context.Context, filterFunc MailFilterFunc, columnFunc ...MailColumnFunc) (*modelpkg.Mail, error) {
var (
model = &modelpkg.Mail{}
db = dao.Table(ctx)
)
if filterFunc != nil {
db = db.Where(filterFunc(dao.Columns))
}
if len(columnFunc) > 0 && columnFunc[0] != nil {
columns := columnFunc[0](dao.Columns)
if len(columns) > 0 {
db = db.Select(columns)
}
}
if rst := db.First(model); rst.Error != nil {
if errors.Is(rst.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, rst.Error
}
return model, nil
}
// Last executes a last command and returns a model for one record in the table.
func (dao *Mail) Last(ctx context.Context, filterFunc MailFilterFunc, columnFunc ...MailColumnFunc) (*modelpkg.Mail, error) {
var (
model = &modelpkg.Mail{}
db = dao.Table(ctx)
)
if filterFunc != nil {
db = db.Where(filterFunc(dao.Columns))
}
if len(columnFunc) > 0 && columnFunc[0] != nil {
columns := columnFunc[0](dao.Columns)
if len(columns) > 0 {
db = db.Select(columns)
}
}
if rst := db.Last(model); rst.Error != nil {
if errors.Is(rst.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, rst.Error
}
return model, nil
}
// FindOne executes a take command and returns a model for one record in the table.
func (dao *Mail) FindOne(ctx context.Context, filterFunc MailFilterFunc, columnFunc ...MailColumnFunc) (*modelpkg.Mail, error) {
var (
model = &modelpkg.Mail{}
db = dao.Table(ctx)
)
if filterFunc != nil {
db = db.Where(filterFunc(dao.Columns))
}
if len(columnFunc) > 0 && columnFunc[0] != nil {
columns := columnFunc[0](dao.Columns)
if len(columns) > 0 {
db = db.Select(columns)
}
}
if rst := db.Take(model); rst.Error != nil {
if errors.Is(rst.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, rst.Error
}
return model, nil
}
// FindMany executes a find command and returns many models the matching documents in the collection.
func (dao *Mail) FindMany(ctx context.Context, filterFunc MailFilterFunc, columnFunc MailColumnFunc, orderFunc MailOrderFunc, limitAndOffset ...int) ([]*modelpkg.Mail, error) {
var (
models = make([]*modelpkg.Mail, 0)
db = dao.Table(ctx)
)
if filterFunc != nil {
db = db.Where(filterFunc(dao.Columns))
}
if columnFunc != nil {
columns := columnFunc(dao.Columns)
if len(columns) > 0 {
db = db.Select(columns)
}
}
if orderFunc != nil {
orders := orderFunc(dao.Columns)
for _, order := range orders {
db = db.Order(fmt.Sprintf("%s %s", order.Column, order.Order))
}
}
if len(limitAndOffset) > 0 {
db = db.Limit(limitAndOffset[0])
}
if len(limitAndOffset) > 1 {
db = db.Offset(limitAndOffset[1])
}
rst := db.Scan(&models)
if rst.Error != nil {
if errors.Is(rst.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, rst.Error
}
return models, nil
}
File Location: example/dao/mail.go
package dao
import (
"github.com/dawnsgo/gorm_dao_generator/example/dao/internal"
"gorm.io/gorm"
)
type (
MailColumns = internal.MailColumns
MailOrderBy = internal.MailOrderBy
)
type Mail struct {
*internal.Mail
}
func NewMail(db *gorm.DB) *Mail {
return &Mail{Mail: internal.NewMail(db)}
}
6-4.Use the generated dao file
File Location: example/main.go
package main
import (
"context"
"github.com/dawnsgo/gorm_dao_generator/example/dao"
"github.com/dawnsgo/gorm_dao_generator/example/model"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"log"
"time"
)
func main() {
// MySQL 8.0+ DSN with allowNativePasswords for authentication compatibility
dsn := "root:123456@tcp(127.0.0.1:3306)/game?charset=utf8mb4&parseTime=True&loc=Local&allowNativePasswords=true"
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: dsn,
}))
if err != nil {
log.Fatalf("connect mysql server failed: %v", err)
}
mailDao := dao.NewMail(db)
baseCtx := context.Background()
_, err = mailDao.Insert(baseCtx, &model.Mail{
Title: "gorm_dao_generator introduction",
Content: "The gorm_dao_generator is a tool for automatically generating Mysql Data Access Object.",
Sender: 1,
Receiver: 2,
Status: 1,
SendTime: time.Now(),
})
if err != nil {
log.Fatalf("failed to insert into mysql database: %v", err)
}
mail, err := mailDao.FindOne(baseCtx, func(cols *dao.MailColumns) interface{} {
return map[string]interface{}{
cols.Receiver: 2,
}
})
if err != nil {
log.Fatalf("failed to find a row of data from mysql database: %v", err)
}
log.Printf("%+v", mail)
}
6-5.Run result:
$ go run main.go
$ 2025/05/14 20:28:41 &{ID:1 Title:gorm_dao_generator introduction Content:The gorm_dao_generator is a tool for automatically generating Mysql Data Access Object. Sender:1 Receiver:2 Status:1 SendTime:2025-05-14 20:28:42 +0800 CST}
Documentation
¶
There is no documentation for this package.
Click to show internal directories.
Click to hide internal directories.