Contents

Gorm gen

Gorm gen

参考链接:

示例代码:

Gen是一个基于GORM的安全ORM框架,其主要通过代码生成方式实现GORM代码封装。使用Gen框架能够自动生成Model结构体和类型安全的CRUD代码,极大提升CRUD效率。

Gen介绍

Gen是由字节跳动无恒实验室与GORM作者联合研发的一个基于GORM的安全ORM框架,主要通过代码生成方式实现GORM代码封装。

Gen框架在GORM框架的基础上提供了以下能力:

  • 基于原始SQL语句生成可重用的CRUD API
  • 生成不使用interface{}的100%安全的DAO API
  • 依据数据库生成遵循GORM约定的结构体Model
  • 支持GORM的所有特性

简单来说,使用Gen框架后我们无需手动定义结构体Model,同时Gen框架也能帮我们生成类型安全的CRUD代码。

更多详细介绍请查看Gen官方文档

此外,Facebook开源的ent也是社区中常用的类似框架,大家可按需选择使用。

Gen 使用

go get grom.io/gen

在项目根目录新建 model文件夹,然后创建 model.go

package model

type Student struct {
	Id   int
	Name string

	TeacherID int
}

type Teacher struct {
	Id   int
	Name string

	// has many
	Student []Student
}

然后使用go 生成代码

创建cmd/gen/generate.go

package main

import (
	"github.com/root/genc/model"

	"gorm.io/gen"
)

//// Dynamic SQL
//type Querier interface {
//	// SELECT * FROM @@table WHERE name = @name{{if role !=""}} AND role = @role{{end}}
//	FilterWithNameAndRole(name, role string) ([]gen.T, error)
//}

func main() {
	g := gen.NewGenerator(gen.Config{
		OutPath: "../../query",
		Mode:    gen.WithoutContext | gen.WithDefaultQuery | gen.WithQueryInterface, // generate mode
	})

	// gormdb, _ := gorm.Open(mysql.Open("root:@(127.0.0.1:3306)/demo?charset=utf8mb4&parseTime=True&loc=Local"))
	//g.UseDB(gormdb) // reuse your gorm db

	// Generate basic type-safe DAO API for struct `model.User` following conventions
	g.ApplyBasic(model.Student{}, model.Teacher{})

	// Generate Type Safe API with Dynamic SQL defined on Querier interface for `model.User` and `model.Company`
	//g.ApplyInterface(func(Querier) {}, model.User{}, model.Company{})

	// Generate the code
	g.Execute()
}

运行命令 go run cmd/gen/generate.go

[root@Sugar genc]🐳 go run cmd/gen/generate.go
2023/11/28 01:10:21 Start generating code.
2023/11/28 01:10:21 generate query file: /Users/root/github/genc/query/students.gen.go
2023/11/28 01:10:21 generate query file: /Users/root/github/genc/query/teachers.gen.go
2023/11/28 01:10:21 generate query file: /Users/root/github/genc/query/gen.go
2023/11/28 01:10:21 Generate code done.

server main文件

cmd/sugar/sugar.go

package main

import (
	"fmt"

	"github.com/glebarez/sqlite"
	"github.com/root/genc/model"
	"github.com/root/genc/query"
	"gorm.io/gorm"
	"gorm.io/gorm/schema"
)

func main() {
	// dsn := "root:12345678@tcp(127.0.0.1:3306)/gorm_learning?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{
		DisableForeignKeyConstraintWhenMigrating: true,
		NamingStrategy: schema.NamingStrategy{
			SingularTable: true, // 设置创建表名时不使用复数
		},
	})
	if err != nil {
		panic(err)
	}
	err = db.AutoMigrate(&model.Student{}, &model.Teacher{})
	if err != nil {
		panic(err)
	}
	query.SetDefault(db)

	// 增
	student1 := model.Student{Name: "student1"}
	student2 := model.Student{Name: "student2"}
	student3 := model.Student{Name: "student3"}
	_ = query.Student.Create(&student1, &student2, &student3)

	teacher1 := model.Teacher{Name: "teacher1"}
	_ = query.Teacher.Create(&teacher1)

	// 删
	_, _ = query.Student.Where(query.Student.Id.Eq(3)).Delete()

	// 改
	_, _ = query.Student.Where(query.Student.Id.Eq(2)).Update(query.Student.Name, "student2_new")

	// 查
	student, _ := query.Student.Where(query.Student.Id.Eq(1)).Take()
	teacher, _ := query.Teacher.Where(query.Teacher.Id.Eq(1)).Take()

	fmt.Println(student) // {1 student1 0}
	fmt.Println(teacher) // {1 teacher1 []}

	// 关联
	_ = query.Teacher.Student.Model(&teacher1).Append(&student1, &student2)
	teacher, _ = query.Teacher.Preload(query.Teacher.Student).Where(query.Teacher.Id.Eq(1)).Take()

	fmt.Println(teacher) // {1 teacher1 [{1 student1 1} {2 student2_new 1}]}

	fmt.Println(query.Student.TableName())
	fmt.Println(query.Teacher.TableName())
}

运行主服务

[root@Sugar genc]🐳 go run cmd/sugar/main.go 
&{1 student1 1}
&{1 teacher1 []}
&{1 teacher1 [{1 student1 1} {2 student2_new 1}]}
student
teacher

更新字段使用对比

GLOBAL_DB.Model(&Student{}).Where("ID = ?", 2).Update("Name", "student2_new")

query.Student.Where(query.Student.Id.Eq(2)).Update(query.Student.Name, "student2_new")