linx93 / gorm-plus

这是一个gorm的增强版,类似mybatis-plus语法。This is a plus version of gorm, which is similar to the mybatis-plus syntax.

Home Page:https://github.com/acmestack/gorm-plus/wiki

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

gorm-plus

这是一个gorm的增强版,类似mybatis-plus语法。

This is an plus version of gorm, which is similar to the mybatis-plus syntax.

下载:

go get github.com/acmestack/gorm-plus

go install github.com/acmestack/gorm-plus/cmd/gplus@latest

生成工具gplus

为什么有需要 gplus?

我们在使用gorm的时候,是需要手写字段名称的,例如这样:

gormDb.Where("username = ? and age = ?","zhangsan",18)

一旦名称长,非常容易误写,而且如果有字段名称修改的话,还需要全局搜索一个个地修改,比较麻烦。

Go没有提供类似Java的lambad表达式或者C#中 nameof 方式直接获取某个对象的字段名称的操作,但是我们可以通过生成代码的方式生成字段名。

所有就有了gplus,它作用就是自动识别结构体,把结构体的字段名生成出来。

使用gplus

通过 gplus gen paths=路径,gplus 会自动识别带有// +gplus:column=true注释的结构体,给这个结构体生成字段。

gplus 会在输入的路径下面生成 zz_gen.column.go文件。

例如:

在example目录下创建了了一个users.go 目录,执行 gplus gen paths=./eample

users.go

// +gplus:column=true

type User struct {
	ID        int64
	Username  string `gorm:"column:username"`
	Password  string
	Address   string
	Age       int
	Phone     string
	Score     int
	Dept      string
	CreatedAt time.Time
	UpdatedAt time.Time
}

zz_gen.column.go (自动生成的)

var UserColumn = struct {
	ID        string
	Username  string
	Password  string
	Address   string
	Age       string
	Phone     string
	Score     string
	Dept      string
	CreatedAt string
	UpdatedAt string
}{
	ID:        "id",
	Username:  "username",
	Password:  "password",
	Address:   "address",
	Age:       "age",
	Phone:     "phone",
	Score:     "score",
	Dept:      "dept",
	CreatedAt: "created_at",
	UpdatedAt: "updated_at",
}

基础操作:

users 表

DROP TABLE IF EXISTS `users`;
CREATE TABLE `users`  (
                          `id` int(0) NOT NULL AUTO_INCREMENT,
                          `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
                          `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
                          `age` int(0) NULL DEFAULT NULL,
                          `phone` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
                          `score` int(0) NULL DEFAULT NULL,
                          `address` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
                          `dept` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL,
                          `created_at` datetime(0) NULL DEFAULT NULL,
                          `updated_at` datetime(0) NULL DEFAULT NULL,
                          PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic;

SET FOREIGN_KEY_CHECKS = 1;

初始化

var GormDb *gorm.DB

func init() {
	dsn := "root:root-abcd-1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	var err error
	GormDb, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		log.Fatalln(err)
	}
	gplus.Init(GormDb)
}


// +gplus:column=true

type User struct {
	ID        int64
	Username  string `gorm:"column:username"`
	Password  string
	Address   string
	Age       int
	Phone     string
	Score     int
	Dept      string
	CreatedAt time.Time
	UpdatedAt time.Time
}

func (User) TableName() string {
	return "Users"
}

Select

func TestSelectById(t *testing.T) {
	user, resultDb := gplus.SelectById[User](1)
	if resultDb.Error != nil {
		if errors.Is(resultDb.Error, gorm.ErrRecordNotFound) {
			log.Fatalln("SelectById Data not found:", resultDb.Error)
		}
		log.Fatalln("SelectById error:", resultDb.Error)
	}
	log.Println("RowsAffected:", resultDb.RowsAffected)
	marshal, _ := json.Marshal(user)
	log.Println(string(marshal))
}

func TestSelectByIds(t *testing.T) {
	var ids []int
	ids = append(ids, 1)
	ids = append(ids, 2)
	users, resultDb := gplus.SelectByIds[User](ids)
	if resultDb.Error != nil {
		log.Fatalln(resultDb.Error)
	}
	log.Println("RowsAffected:", resultDb.RowsAffected)
	marshal, _ := json.Marshal(users)
	log.Println(string(marshal))
}

func TestSelectOne1(t *testing.T) {
	q := gplus.NewQuery[User]()
	q.Eq(UserColumn.Username, "zhangsan1")
	user, resultDb := gplus.SelectOne(q)

	if resultDb.Error != nil {
		if errors.Is(resultDb.Error, gorm.ErrRecordNotFound) {
			log.Fatalln("SelectOne Data not found:", resultDb.Error)
		}
		log.Fatalln("SelectOne error:", resultDb.Error)
	}

	log.Println("RowsAffected:", resultDb.RowsAffected)
	marshal, _ := json.Marshal(user)
	log.Println(string(marshal))
}

func TestSelectOne2(t *testing.T) {
	q := gplus.NewQuery[User]()
	q.Eq(UserColumn.Username, "zhangsan").
		Select(UserColumn.Username, UserColumn.Password)
	user, resultDb := gplus.SelectOne(q)

	if resultDb.Error != nil {
		if errors.Is(resultDb.Error, gorm.ErrRecordNotFound) {
			log.Fatalln("SelectOne Data not found:", resultDb.Error)
		}
		log.Fatalln("SelectOne error:", resultDb.Error)
	}

	log.Println("RowsAffected:", resultDb.RowsAffected)
	marshal, _ := json.Marshal(user)
	log.Println(string(marshal))
}

func TestSelectList(t *testing.T) {
	q := gplus.NewQuery[User]()
	q.Eq(UserColumn.Username, "zhangsan")
	users, resultDb := gplus.SelectList(q)
	if resultDb.Error != nil {
		log.Fatalln("error:", resultDb.Error)
	}
	for _, u := range users {
		marshal, _ := json.Marshal(u)
		log.Println(string(marshal))
	}
}

func TestSelectBracketList(t *testing.T) {
	q := gplus.NewQuery[User]()
	bracketQuery := gplus.NewQuery[User]()
	bracketQuery.Eq(UserColumn.Address, "上海").Or().Eq(UserColumn.Address, "北京")

	q.Eq(UserColumn.Username, "zhangsan").AndBracket(bracketQuery)
	users, resultDb := gplus.SelectList(q)
	if resultDb.Error != nil {
		log.Fatalln("error:", resultDb.Error)
	}
	for _, u := range users {
		marshal, _ := json.Marshal(u)
		log.Println(string(marshal))
	}
}

func TestSelectTableList(t *testing.T) {
	type deptCount struct {
		Dept  string
		Count string
	}
	q := gplus.NewQuery[User]()
	q.Group(UserColumn.Dept).Select(UserColumn.Dept, "count(*) as count")
	users, resultDb := gplus.SelectListModel[User, deptCount](q)
	if resultDb.Error != nil {
		log.Fatalln("error:", resultDb.Error)
	}
	for _, u := range users {
		marshal, _ := json.Marshal(u)
		log.Println(string(marshal))
	}
}

func TestSelectPage(t *testing.T) {
	q := gplus.NewQuery[User]()
	q.Eq(UserColumn.Age, 18)
	page := gplus.NewPage[User](1, 10)
	pageResult, resultDb := gplus.SelectPage(page, q)
	if resultDb.Error != nil {
		log.Fatalln("error:", resultDb.Error)
	}
	log.Println("total", pageResult.Total)
	for _, u := range pageResult.Records {
		marshal, _ := json.Marshal(u)
		log.Println(string(marshal))
	}
}

func TestSelectTablePage(t *testing.T) {
	type deptCount struct {
		Dept  string
		Count string
	}
	q := gplus.NewQuery[User]()
	q.Group(UserColumn.Dept).Select(UserColumn.Dept, "count(*) as count")
	page := gplus.NewPage[deptCount](1, 2)
	pageResult, resultDb := gplus.SelectPageModel[User, deptCount](page, q)
	if resultDb.Error != nil {
		log.Fatalln("error:", resultDb.Error)
	}
	log.Println("total:", pageResult.Total)
	for _, u := range pageResult.Records {
		marshal, _ := json.Marshal(u)
		log.Println(string(marshal))
	}
}

func TestSelectCount(t *testing.T) {
	q := gplus.NewQuery[User]()
	q.Eq(UserColumn.Age, 18)
	count, resultDb := gplus.SelectCount(q)
	if resultDb.Error != nil {
		log.Fatalln("error:", resultDb.Error)
	}
	log.Println("count:", count)
}

Insert

func TestInsert(t *testing.T) {
	user := &User{Username: "zhangsan", Password: "123456", Age: 18, Score: 100, Dept: "A部门"}
	result := gplus.Insert(user)
	if result.Error != nil {
		fmt.Println(result.Error)
	}
	fmt.Println(result.RowsAffected)
}

func TestInsertBatch(t *testing.T) {
	user1 := &User{Username: "zhangsan1", Password: "123456", Age: 18, Score: 12, Dept: "导弹部门"}
	user2 := &User{Username: "lisi", Password: "123456", Age: 16, Score: 34, Dept: "投诉部门"}
	user3 := &User{Username: "wangwu", Password: "123456", Age: 26, Score: 33, Dept: "研发部门"}
	user4 := &User{Username: "zhangsan4", Password: "123456", Age: 30, Score: 11, Dept: "产品部门"}
	user5 := &User{Username: "zhangsan5", Password: "123456", Age: 12, Score: 34, Dept: "产品部门1"}
	user6 := &User{Username: "zhangsan6", Password: "123456", Age: 45, Score: 123, Dept: "产品部门12"}

	var users []*User
	users = append(users, user1)
	users = append(users, user2)
	users = append(users, user3)
	users = append(users, user4)
	users = append(users, user5)
	users = append(users, user6)

	result := gplus.InsertBatch[User](users)
	if result.Error != nil {
		fmt.Println(result.Error)
	}
	fmt.Println(result.RowsAffected)
	for _, u := range users {
		marshal, _ := json.Marshal(u)
		fmt.Println(string(marshal))
	}
}

func TestInsertBatchSize(t *testing.T) {
	user1 := &User{Username: "zhangsan1", Password: "123456", Age: 18, Score: 12, Dept: "导弹部门"}
	user2 := &User{Username: "lisi", Password: "123456", Age: 16, Score: 34, Dept: "投诉部门"}
	user3 := &User{Username: "wangwu", Password: "123456", Age: 26, Score: 33, Dept: "研发部门"}
	user4 := &User{Username: "zhangsan4", Password: "123456", Age: 30, Score: 11, Dept: "产品部门"}
	user5 := &User{Username: "zhangsan5", Password: "123456", Age: 12, Score: 34, Dept: "产品部门1"}
	user6 := &User{Username: "zhangsan6", Password: "123456", Age: 45, Score: 123, Dept: "产品部门12"}

	var users []*User
	users = append(users, user1)
	users = append(users, user2)
	users = append(users, user3)
	users = append(users, user4)
	users = append(users, user5)
	users = append(users, user6)

	result := gplus.InsertBatchSize[User](users, 3)
	if result.Error != nil {
		fmt.Println(result.Error)
	}
	fmt.Println(result.RowsAffected)
	for _, u := range users {
		marshal, _ := json.Marshal(u)
		fmt.Println(string(marshal))
	}
}

Update

func TestUpdateById(t *testing.T) {
	user := &User{ID: 1, Username: "zhangsan", Password: "123456", Age: 18, Score: 100, Dept: "A部门asdfasdf"}
	result := gplus.UpdateById(user)
	if result.Error != nil {
		fmt.Println(result.Error)
	}
	fmt.Println(result.RowsAffected)
}

func TestUpdate(t *testing.T) {
	q := gplus.NewQuery[User]()
	q.Eq(UserColumn.Username, "zhangsan").Set(UserColumn.Dept, "相关部门123123").
		Set(UserColumn.Phone, 12312)
	result := gplus.Update(q)
	if result.Error != nil {
		fmt.Println(result.Error)
	}
	fmt.Println(result.RowsAffected)
}

Delete

func TestDeleteById(t *testing.T) {
	result := gplus.DeleteById[User](13)
	if result.Error != nil {
		fmt.Println(result.Error)
	}
	fmt.Println(result.RowsAffected)
}

func TestDelete(t *testing.T) {
	q := gplus.NewQuery[User]()
	q.Ge(UserColumn.Age, 50)
	result := gplus.Delete(q)
	if result.Error != nil {
		fmt.Println(result.Error)
	}
	fmt.Println(result.RowsAffected)
}

通用操作

您可以在结构体中嵌入gplus.CommonDao获得通用的操作

初始化

var GormDb *gorm.DB

func init() {
	dsn := "root:root-abcd-1234@tcp(127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
	var err error
	GormDb, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
		Logger: logger.Default.LogMode(logger.Info),
	})
	if err != nil {
		log.Fatalln(err)
	}
	gplus.Init(GormDb)
}

// +gplus:column=true

type User struct {
	ID        int64
	Username  string `gorm:"column:username"`
	Password  string
	Address   string
	Age       int
	Phone     string
	Score     int
	Dept      string
	CreatedAt time.Time
	UpdatedAt time.Time
}

func (User) TableName() string {
	return "Users"
}


var userDao = NewUserDao[User]()

type UserDao[T any] struct {
	gplus.CommonDao[T]
}

func NewUserDao[T any]() *UserDao[T] {
	return &UserDao[T]{}
}

查询

func TestGetById(t *testing.T) {
	user, resultDb := userDao.GetById(2)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	marshal, _ := json.Marshal(user)
	fmt.Println("user1:", string(marshal))
}

func TestGetByOne(t *testing.T) {
	query := gplus.NewQuery[User]()
	query.Eq(UserColumn.Username, "zhangsan1")
	user, resultDb := userDao.GetOne(query)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	marshal, _ := json.Marshal(user)
	fmt.Println("user1:", string(marshal))
}

func TestListAll(t *testing.T) {
	users, resultDb := userDao.ListAll()
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	for _, v := range users {
		marshal, _ := json.Marshal(v)
		fmt.Println("u:", string(marshal))
	}
}

func TestList(t *testing.T) {
	query := gplus.NewQuery[User]()
	query.Eq(UserColumn.Username, "zhangsan1")
	users, resultDb := userDao.List(query)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	for _, v := range users {
		marshal, _ := json.Marshal(v)
		fmt.Println("u:", string(marshal))
	}
}

func TestPageAll(t *testing.T) {
	page := gplus.NewPage[User](1, 2)
	page, resultDb := userDao.PageAll(page)
	fmt.Println("page total:", page.Total)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	for _, v := range page.Records {
		marshal, _ := json.Marshal(v)
		fmt.Println("u:", string(marshal))
	}
}

func TestPage(t *testing.T) {
	page := gplus.NewPage[User](1, 2)
	query := gplus.NewQuery[User]()
	query.Eq(UserColumn.Username, "zhangsan1")
	page, resultDb := userDao.Page(page, query)
	fmt.Println("page total:", page.Total)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	for _, v := range page.Records {
		marshal, _ := json.Marshal(v)
		fmt.Println("u:", string(marshal))
	}
}

保存

func TestSave(t *testing.T) {
	user1 := &User{Username: "zhangsan1", Password: "123456", Age: 18, Score: 12, Dept: "导弹部门"}
	resultDb := userDao.Save(user1)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	marshal, _ := json.Marshal(user1)
	fmt.Println("user1:", string(marshal))
}

func TestSaveBatch(t *testing.T) {
	user1 := &User{Username: "zhangsan1", Password: "123456", Age: 11, Score: 12, Dept: "导弹部门"}
	user2 := &User{Username: "zhangsan1", Password: "123456", Age: 13, Score: 12, Dept: "导弹部门"}
	var users []*User
	users = append(users, user1)
	users = append(users, user2)
	resultDb := userDao.SaveBatch(users)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	for _, u := range users {
		marshal, _ := json.Marshal(u)
		fmt.Println("user:", string(marshal))
	}
}

func TestSaveBatchSize(t *testing.T) {
	user1 := &User{Username: "zhangsan1", Password: "123456", Age: 11, Score: 12, Dept: "导弹部门"}
	user2 := &User{Username: "zhangsan1", Password: "123456", Age: 13, Score: 12, Dept: "导弹部门"}
	user3 := &User{Username: "zhangsan1", Password: "123456", Age: 13, Score: 12, Dept: "导弹部门"}
	user4 := &User{Username: "zhangsan1", Password: "123456", Age: 13, Score: 12, Dept: "导弹部门"}
	var users []*User
	users = append(users, user1)
	users = append(users, user2)
	users = append(users, user3)
	users = append(users, user4)
	resultDb := userDao.SaveBatchSize(users, 2)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
	for _, u := range users {
		marshal, _ := json.Marshal(u)
		fmt.Println("user:", string(marshal))
	}
}

更新

func TestUpdateById(t *testing.T) {
	user4 := &User{ID: 4, Username: "zhangsan666", Password: "123456", Age: 13, Score: 12, Dept: "导弹部门"}
	userDao.UpdateById(user4)
}

func TestUpdate(t *testing.T) {
	query := gplus.NewQuery[User]()
	query.Eq(UserColumn.Username, "zhangsan1").Set(UserColumn.Age, 50)
	userDao.Update(query)
}

删除

func TestRemoveById(t *testing.T) {
	resultDb := userDao.RemoveById(7)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
}

func TestRemoveByIds(t *testing.T) {
	var ids []int
	ids = append(ids, 5)
	ids = append(ids, 6)
	resultDb := userDao.RemoveByIds(ids)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
}

func TestRemove(t *testing.T) {
	query := gplus.NewQuery[User]()
	query.Eq(UserColumn.Username, "lisi")
	resultDb := userDao.Remove(query)
	fmt.Println("RowsAffected:", resultDb.RowsAffected)
}

About

这是一个gorm的增强版,类似mybatis-plus语法。This is a plus version of gorm, which is similar to the mybatis-plus syntax.

https://github.com/acmestack/gorm-plus/wiki

License:Apache License 2.0


Languages

Language:Go 100.0%