实践:使用Gorm实现增删改查 | 青训营

140 阅读3分钟

Gen根据数据库自动生成模型结构体使用案例

Gorm-Gen概念介绍

gorm-gen是基于GORM,更安全更友好的ORM工具,可生成model和curd代码。

相比较Gorm的优势:

  • 连接数据库的表生成相应的结构体model,再也不用手敲了,如果以后数据库有表的字段发生改动,只需重新生成即可
  • 提供crud的API类似于mybatisplus,做crud更方便
  • 有条件查询或更新时,表的列名不用写进字符串里,有列名改动不用手动去查找替换了
  • 完全兼容GORM

如何得到建表语句

  • mysqldump只备份表结构

    mysqldump --no-data --databases mydatabase1 mydatabase2 mydatabase3 > test.dump
    
  • show create table xxx

构建生成代码

  1. 将数据库DSN更新为自己的DSN。
  2. 在(cmd\generate\main.go)中写入配置。
  3. 使用以下命令生成代码,可以从数据库或结构的基本类型安全DAO API生成结构。

生成构建代码:

package main

import (
	"fmt"

	"gorm.io/driver/mysql"
	"gorm.io/gen"
	"gorm.io/gorm"
)

const MySQLDSN = "root:20211099@tcp(127.0.0.1:3306)/wechatdemo?charset=utf8mb4&parseTime=True&loc=Local"

func main() {
	//连接数据库
	db, err := gorm.Open(mysql.Open(MySQLDSN))
	if err != nil {
		panic(fmt.Errorf("cannot establish db connection: %w", err))
	}

	g := gen.NewGenerator(gen.Config{
		/* 相对执行go run的路径,自动创建目录 */
		OutPath:      "dal",
		ModelPkgPath: "model",
		// WithDefaultQuery 生成默认查询结构体(作为全局变量使用), 即`Q`结构体和其字段(各表模型)
		// WithoutContext 生成没有context调用限制的代码供查询
		// WithQueryInterface 生成interface形式的查询代码(可导出), 如`Where()`方法返回的就是一个可导出的接口类型
		Mode: gen.WithQueryInterface | gen.WithDefaultQuery | gen.WithoutContext,

		// 表字段可为 null 值时, 对应结体字段使用指针类型
		FieldNullable: false,

		//如果数据库中字段有默认值,则生成指针类型的字段,以避免零值(zero-value)问题
		FieldCoverable: false,

		// 模型结构体字段的数字类型的符号表示是否与表字段的一致, `false`指示都用有符号类型
		FieldSignable: false, // detect integer field's unsigned type, adjust generated data type
		// 生成 gorm 标签的字段索引属性
		FieldWithIndexTag: false, // generate with gorm index tag
		// 生成 gorm 标签的字段类型属性
		FieldWithTypeTag: true, // generate with gorm column type tag
	})

	g.UseDB(db)
	g.ApplyBasic(g.GenerateAllTable()...)
	g.Execute()
}

其中,WithDefaultQuery 生成默认查询结构体(作为全局变量使用), 即Q结构体和其字段(各表模型) WithoutContext 生成没有context调用限制的代码供查询 WithQueryInterface 生成interface形式的查询代码(可导出), 如Where()方法返回的就是一个可导出的接口类型


在根目录运行该代码完毕,根据生成代码内容,代码结构如下:

-
 --cmd
   ---generate
      ----main.go
 --dal
   ---
 --model
   ---
 --go.mod
 --go.sum
 --main.go

测试——增删改查

在dal文件夹新建一个db文件夹用于与数据库的交互

package db

import (
	"gorm/gen/try/dal"
	"gorm/gen/try/model"

	"gorm.io/gorm"
)

func MCreateUser(users []*model.User, db *gorm.DB) error {
	dal.SetDefault(db)
	return dal.User.CreateInBatches(users, 100)
}

package db

import (
	"fmt"
	"gorm/gen/try/dal"

	"gorm.io/gorm"
)

func DeleteUser(userID int, db *gorm.DB) {
	dal.SetDefault(db)
	u := dal.User
	res, err := u.Where(u.UserID.Eq(int32(userID)), u.UserName.Eq("hobush")).Delete()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(res.RowsAffected)
	}
}

package db

import (
	"fmt"
	"gorm/gen/try/dal"
	"gorm/gen/try/model"

	"gorm.io/gorm"
)

func UpdateUser(user model.User, db *gorm.DB) {
	dal.SetDefault(db)
	u := dal.User
	res, err := u.Where(u.UserID.Eq(10)).Updates(
		model.User{
			UserName: "hobush22",
		})
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(res)
	}
}

package db

import (
	"fmt"
	"gorm/gen/try/dal"
	"gorm/gen/try/model"

	"gorm.io/gorm"
)

func MQueryUser(user model.User, db *gorm.DB) ([]*model.User, error) {
	dal.SetDefault(db)
	u := dal.User
	res, err := u.Where(u.UserID.Eq(user.UserID)).Find()
	if err != nil {
		fmt.Println(err)
	} else {
		fmt.Println(res)
	}
	return res, err
}

官方文档

总结

gorm/gengorm/gen 是 GORM 的代码生成工具。通过使用 gorm/gen,你可以根据数据库表结构自动生成对应的 GORM 模型代码。它能够自动读取数据库的元数据,并生成包含模型定义、字段映射、关联关系等内容的 Go 代码文件。这样你就可以通过运行 gorm/gen 命令来自动生成 GORM 模型代码,避免手动编写重复的代码。